PHP 5.4 Pass-by-reference per tempo di chiamata - È disponibile una soluzione semplice?


Risposte:


344

Dovresti indicare la chiamata come riferimento nella definizione della funzione, non la chiamata effettiva. Da quando PHP ha iniziato a mostrare gli errori di deprecazione nella versione 5.3, direi che sarebbe una buona idea riscrivere il codice.

Dalla documentazione :

Non esiste un segno di riferimento su una chiamata di funzione - solo sulle definizioni di funzione. Le definizioni delle funzioni da sole sono sufficienti per passare correttamente l'argomento per riferimento. A partire da PHP 5.3.0, riceverai un avviso che dice che "pass-by-reference-time di chiamata" è obsoleto quando lo usi &in foo(&$a);.

Ad esempio, invece di utilizzare:

// Wrong way!
myFunc(&$arg);               # Deprecated pass-by-reference argument
function myFunc($arg) { }

Uso:

// Right way!
myFunc($var);                # pass-by-value argument
function myFunc(&$arg) { }

9
Deprecazione è da PHP 5.0.0, indietro quel tempo dando E_COMPILE_WARNINGerrore di livello, per riferimento: php.net/manual/en/...
hakre

5
Ho avuto questo errore ma avevo bisogno di rimuovere il comando di aggiunta alla variabile.
Diana,

2
L'ho usato nel vecchio codice per un oggetto chiamato event (& $ event) e ho dovuto rimuovere la e commerciale perché il messaggio di errore scomparisse.
Natalia,

1
in tutti i miei anni come sviluppatore non ho mai avuto bisogno di usare e su php. mai e poi mai. questo era esattamente quello che stavo cercando. fantastico
Juan Vilar,

8
per le persone nei commenti, tenere presente che la rimozione di & può comportare risultati imprevisti poiché eventuali modifiche alla variabile non saranno più condivise ma saranno visibili solo all'ambito locale delle funzioni. Quindi, a meno che tu non sappia cosa fa il codice, ti consiglio di correggerlo come descritto sopra invece di rimuovere semplicemente il carattere &
xorinzor

8

Per chiunque, come me, legge questo perché ha bisogno di aggiornare un gigantesco progetto legacy a 5.6: come sottolineano le risposte qui, non esiste una soluzione rapida: devi davvero trovare manualmente ogni occorrenza del problema e risolverlo .

Il modo più conveniente che ho trovato per trovare tutte le linee problematiche in un progetto (a meno di usare un analizzatore di codice statico completo, che è molto preciso ma non ne conosco nessuno che ti porti subito nella posizione corretta nell'editor) stava usando Visual Studio Code, che ha una bella linter PHP integrata, e la sua funzione di ricerca che consente la ricerca tramite Regex. (Ovviamente, puoi usare qualsiasi editor IDE / Code per questo che fa linting PHP e ricerche Regex.)

Usando questo regex:

^(?!.*function).*(\&\$)

è possibile cercare in tutto il progetto la presenza di &$ solo in righe che non sono una definizione di funzione.

Ciò rivela ancora molti falsi positivi, ma semplifica il lavoro.

Il browser dei risultati di ricerca di VSCode semplifica la navigazione e la ricerca delle linee offensive: basta fare clic su ciascun risultato e cercare quelli evidenziati in rosso dall'interfaccia. Quelli che devi correggere.


1
Questo è quello che stavo cercando!
Sonny,

4
Regex più accurato che sto usando per questo scopo:(?<!function)[:> ][a-zA-Z0-9_]+(?<!foreach|array)\s?\([^()]*&\$
Mojo

basta usare phpcs, scava ogni file che ha questo per te.
Thomas Cheng,

6

PHP e riferimenti non sono abbastanza intuitivi. Se usato in modo appropriato, i riferimenti nei posti giusti possono fornire grandi miglioramenti delle prestazioni o evitare soluzioni molto brutte e codice insolito.

Quanto segue produrrà un errore:

 function f(&$v){$v = true;}
 f(&$v);

 function f($v){$v = true;}
 f(&$v);

Nessuno di questi deve fallire in quanto potrebbe seguire le regole seguenti ma senza dubbio è stato rimosso o disabilitato per evitare molta confusione ereditaria.

Se hanno funzionato, entrambi implicano una conversione ridondante in riferimento e la seconda comporta anche una conversione ridondante in una variabile contenuta con ambito.

Il secondo era possibile consentire il passaggio di un riferimento al codice che non era destinato a funzionare con i riferimenti. Questo è estremamente brutto per la manutenibilità.

Questo non farà nulla:

 function f($v){$v = true;}
 $r = &$v;
 f($r);

Più specificamente, trasforma il riferimento in una normale variabile in quanto non è stato richiesto un riferimento.

Questo funzionerà:

 function f(&$v){$v = true;}
 f($v);

Questo vede che stai passando un non-riferimento ma vuoi un riferimento, quindi lo trasforma in un riferimento.

Ciò significa che non è possibile passare un riferimento a una funzione in cui un riferimento non viene esplicitamente richiesto per renderlo una delle poche aree in cui PHP è rigoroso nel passaggio di tipi o in questo caso più di un meta-tipo.

Se hai bisogno di un comportamento più dinamico questo funzionerà:

 function f(&$v){$v = true;}
 $v = array(false,false,false);
 $r = &$v[1];
 f($r);

Qui vede che vuoi un riferimento e hai già un riferimento, quindi lo lascia da solo. Potrebbe anche incatenare il riferimento ma ne dubito.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.