2010-03-01 4 views
78
$el = array_shift($instance->find(..)) 

Le code ci-dessus présente en quelque sorte la stricte mise en garde des standars, mais ce ne sera pas:normes strictes: Seules les variables doivent être transmises par référence

function get_arr(){ 
    return array(1,2); 
} 
$el = array_shift(get_arr()); 

Alors, quand il compte l'avertissement de toute façon?

+1

Que retourne $ instance-> find (..)? –

+2

Voici la solution: http://stackoverflow.com/questions/9848295/strict-standards-only-variables-should-be-passed-by-reference-error – ajaristi

+0

Je pense que les exemples (ou la logique) pourraient être à l'envers dans la question, puisque le deuxième exemple (fonction 'get_arr()') ** produit ** l'avis de normes strictes (testé PHP 5.2 et PHP 5.5). – MrWhite

Répondre

7

$instance->find() renvoie la référence à la variable.

Vous obtenez le rapport lorsque vous essayez d'utiliser cette référence en tant qu'argument pour fonctionner, sans le stocker au préalable dans la variable.

Cela permet d'éviter les fuites de mémoire et deviendra probablement une erreur dans les prochaines versions de PHP.

Votre 2ème code de jetterait erreur si elle écrit comme (notez le & dans la signature de fonction):

function &get_arr(){ 
    return array(1,2); 
} 
$el = array_shift(get_arr()); 

donc une solution rapide (et pas si agréable) serait:

$el = array_shift($tmp = $instance->find(..)); 

Fondamentalement, vous faites d'abord une affectation à une variable temporaire, et envoyez la variable en tant qu'argument.

+1

Je l'ai essayé précédemment, ne fonctionne pas – user198729

+0

Cela devrait fonctionner maintenant (vérifié il). Pour renvoyer une référence, vous devez la déclarer à la signature de la méthode, et non retourner la déclaration (ma faute). – Sagi

+0

Non, je ne peux pas changer la signature. La variable intermédiaire @ pygorex1 peut résoudre ce problème, mais elle semble redondante, n'est-ce pas? – user198729

90

Consultez le code suivant:

error_reporting(E_STRICT); 
class test { 
    function test_arr(&$a) { 
     var_dump($a); 
    } 
    function get_arr() { 
     return array(1,2); 
    } 
} 

$t= new test; 
$t->test_arr($t->get_arr()); 

Cela va générer la sortie suivante:

Strict Standards: Only variables should be passed by reference in test.php on line 14 
array(2) { 
    [0]=> 
    int(1) 
    [1]=> 
    int(2) 
} 

La raison? La méthode test::get_arr() n'est pas une variable et en mode strict cela va générer un avertissement. Ce comportement est extrêmement non intuitif car la méthode get_arr()renvoie une valeur de tableau.

Pour contourner cette erreur en mode strict, soit changer la signature de la méthode de sorte qu'il n'utilise une référence:

function test_arr($a) { 
    var_dump($a); 
} 

Puisque vous ne pouvez pas changer la signature de array_shift vous pouvez également utiliser un variable intermédiaire:

$inter= get_arr(); 
$el= array_shift($inter); 
+4

Semble qu'il n'y a aucun moyen d'éviter d'utiliser '$ inter'. – user198729

+7

@ user198729: Je cherchais une explication ou une correction aussi, et j'ai trouvé que vous pouvez utiliser current() pour le premier élément. Alas end() ne fonctionne pas pour le dernier puisqu'il "avance le pointeur interne vers le dernier élément". current (array_reverse (somefunction())) fonctionne (oui, c'est idiot) – MSpreij

+2

C'est très bête. –

3

Le deuxième extrait ne fonctionne pas non plus et c'est pourquoi. array_shift est une fonction modificatrice qui change d'argument, donc elle attend que son paramètre soit une référence, et vous ne pouvez pas référencer quelque chose qui n'est pas une variable. Voir les explications de Rasmus ici: http://bugs.php.net/bug.php?id=48937

5

La cause de l'erreur est l'utilisation de la fonction interne PHP Programming Structures Structures, array_shift() [php.net/end]. La fonction prend un tableau en tant que paramètre. Bien qu'une esperluette soit indiquée dans le prototype de "array_shift()" dans le manuel ", il n'y a pas de documentation d'avertissement dans la définition étendue de cette fonction, et il n'y a pas d'explication apparente que le paramètre est effectivement transmis par référence. Je ne comprenais pas, il était donc difficile pour moi de détecter la cause de l'erreur.

Code Reproduire:

function get_arr() 
{ 
return array(1,2); 
} 
$array = get_arr(); 
$el = array_shift($array); 
3

Ce code:

$monthly_index = array_shift(unpack('H*', date('m/Y'))); 

Modifier à:

$date_time = date('m/Y'); 
$unpack = unpack('H*', $date_time); 
array_shift($unpack); 
-2

Eh bien, dans les cas évidents comme ça, vous pouvez toujours dire PHP pour supprimer les messages en utilisant "@" devant la fonction.

$monthly_index = @array_shift(unpack('H*', date('m/Y')));

Il ne peut pas être l'une des meilleures pratiques de programmation pour supprimer toutes les erreurs de cette façon, mais dans certains cas (comme celui-ci), il est très pratique et est acceptable. En conséquence, je suis sûr que votre ami SysAdmin sera satisfait d'un "error.log" moins pollué. ;)

+0

Je ne sais pas qui a downvoted cette réponse, mais la solution présentée fonctionne et c'est une technique standard PHP. Vraiment décevant ... La prochaine fois je pourrais ne plus répondre à une question ... :( –

+3

Je suppose que c'était parce que la suppression du message d'erreur ne résout pas le problème avec le code.Que ferez-vous lorsque ce type d'erreur change de E_STRICT à E_ERROR dans une prochaine version de PHP et votre code ne s'exécute plus, et ne génère pas d'erreur/sortie – Luke

+0

L'utilisation de la suppression des erreurs n'est jamais la solution. La communauté PHP essaie de mettre fin à l'utilisation de @ par nouveaux codeurs, donc s'il vous plaît ne conseille pas à quiconque de l'utiliser –

Questions connexes