web-dev-qa-db-fra.com

Seules les variables peuvent être passées par référence

J'ai eu la brillante idée d'utiliser un gestionnaire d'erreur personnalisé qui m'a conduit dans un terrier de lapin.

Le code suivant donne (avec et sans gestionnaire d'erreur personnalisé): Erreur fatale: seules les variables peuvent être transmises par référence

function foo(){
    $b=array_pop(array("a","b","c"));
    return $b;
}
print_r(foo());

Le code suivant donne ( uniquement avec un gestionnaire d’erreurs personnalisé ): (2048) Seules les variables doivent être transmises par référence

function foo(){
    $a=explode( '/' , 'a/b/c');
    $c=array_pop(array_slice($a,-2,1));
    return $c;
}
print_r(foo());

Le second m'inquiète car j'ai beaucoup de code «compact». Donc, j'ai abandonné l'idée brillante d'utiliser un gestionnaire d'erreurs personnalisé (pour améliorer mon module de journalisation) ou développer tout mon code.

Quelqu'un avec de meilleures idées? Aussi, WTF?

METTRE À JOUR:

Grâce aux réponses, j'ai appris quelque chose sur la façon dont php gère les erreurs. La confusion de E_ALL n'incluant pas E_STRICT (php 5) n'est pas cool.

De plus, la création de votre propre gestionnaire d'erreurs personnalisé active E_STRICT par défaut et c'est là que les problèmes commencent.

La morale de l'histoire est d'utiliser votre propre gestionnaire d'erreurs pour les capturer avec TOUT et d'utiliser les constantes d'erreur (E_STRICT, E_USER_WARNING, E_USER_ERROR, etc.) pour effectuer votre filtrage.

En ce qui concerne le "problème de corruption de mémoire" avec des références variables et certaines fonctions, que puis-je dire? Doublement pas cool. Je vais (ce qui ne veut pas dire que vous devriez) ignorer E_STRICT dans mon gestionnaire d'erreurs et la vie continue.

17
zaf

array_pop () essaye de changer cette valeur qui est passée en paramètre. Maintenant, dans votre deuxième exemple, il s'agit de la valeur de retour de array_slice (). En termes de moteur, il s'agit d'une "valeur temporaire" et une telle valeur ne peut pas être transmise par des références. ce dont vous avez besoin est une variable temporaire:

function foo(){
    $a=explode( '/' , 'a/b/c');
    $b=array_slice($a,-2,1);
    $c=array_pop($b);
    return $c;
}
print_r(foo());

Ensuite, une référence à $ b peut être passée à array_pop (). Voir http://php.net/references pour plus de détails sur les références.

18
johannes

Voici ce que je reçois lorsque j'essaie votre deuxième extrait de code php dans php-cli après la définition de error_reporting sur E_ALL | E_STRICT

    gparis@techosaure:~/workspace/universcine.com$ php -a
Interactive Shell

php > function foo(){
php {     $a=explode( '/' , 'a/b/c');
php {     $c=array_pop(array_slice($a,-2,1));
php {     return $c;
php { }
php > print_r(foo());
PHP Strict standards:  Only variables should be passed by reference in php Shell code on line 3
PHP Stack trace:
PHP   1. {main}() php Shell code:0
PHP   2. foo() php Shell code:1

Comme vous pouvez le constater, ce ne sont que des normes strictes. Et vous pouvez facilement laisser votre gestionnaire d'erreur personnalisé les ignorer (en fonction de la valeur que vous obtenez: 2048 par exemple, ici).

Depuis PHP 5.3, E_ALL n'inclut pas E_STRICT, regardez ceci: 

php > foreach(array("E_ALL", "E_DEPRECATED", "E_STRICT", "E_NOTICE", "E_PARSE", "E_WARNING") as $const) echo $const . "  :\t" . constant($const) ."\t". decbin(constant($const)). "\n";
E_ALL  :        30719   111011111111111
E_DEPRECATED  : 8192     10000000000000
E_STRICT  :     2048       100000000000
E_NOTICE  :     8                  1000
E_PARSE  :      4                   100
E_WARNING  :    2                    10

Depuis php 5.4, E_ALL inclut E_STRICT:

E_ALL  :            32767   111111111111111
E_DEPRECATED  :     8192     10000000000000
E_STRICT  :         2048       100000000000
E_NOTICE  :         8                  1000
E_PARSE  :          4                   100
E_WARNING  :        2                    10
9
greg0ire

C'est un problème de corruption de mémoire (selon PHP équipe de développement). Il suffit de lancer une mission:

function foo(){
    $b = array_pop($arr = array("a","b","c"));
    return $b;
}
print_r(foo());

:

function foo(){
    $a = explode( '/' , 'a/b/c');
    $c = array_pop($arr = array_slice($a,-2,1));
    return $c;
}
print_r(foo());

Le second produit un E_STRICT. Vous pouvez gérer cela différemment dans votre gestionnaire d'erreurs si vous le souhaitez (si vous ne souhaitez pas modifier ces fonctions).

4
webbiedave

array_pop() modifie la valeur transmise, d'où provient l'erreur. Une fonction ne peut pas être modifiée. En d'autres termes, vous devez d'abord affecter le tableau à une variable (réf: manual ), puis exécuter array_pop().

Le code dont vous avez besoin est le suivant:

function foo(){
    $a = array("a","b","c");
    $b = array_pop($a);
    return $b;
}

Edit: Les deux fonctions que vous avez mentionnées ont le même problème. Assignez le tableau à une variable et transmettez-la à array_pop().

1
Joseph

Je pense que maintenant (depuis php 5) il devrait être:

function &foo(){ //NOTICE THE &
    $b=array_pop(array("a","b","c"));
    return $b;
}
print_r(foo());

et

function &foo(){ //NOTICE THE &
    $a=explode( '/' , 'a/b/c');
    $c=array_pop(array_slice($a, $b = -2, $c = 1)); //NOW NO DIRECT VALUES ARE PASSED IT MUST BE VARIABLES
    return $c;
}
print_r(foo());

mais je ne suis qu'un débutant :)

1
popeyems
0
broadband

Essaye ça:

function foo(){
    $a = array("a","b","c");
    $b = array_pop($a);
    return $b;
}
0
baloo