php - una - Solo se pueden pasar las variables por referencia
paso por referencia (7)
Tuve la brillante idea de usar un controlador de errores personalizado que me llevó por un agujero de conejo.
El siguiente código proporciona (con y sin controlador de errores personalizado): Error grave: solo se pueden pasar las variables por referencia
function foo(){
$b=array_pop(array("a","b","c"));
return $b;
}
print_r(foo());
El siguiente código proporciona ( solo con un controlador de errores personalizado ): (2048) Solo las variables deben pasarse por referencia
function foo(){
$a=explode( ''/'' , ''a/b/c'');
$c=array_pop(array_slice($a,-2,1));
return $c;
}
print_r(foo());
El segundo me preocupa porque tengo un montón de código "compacto". Entonces, o me deshago de la brillante idea de usar un controlador de errores personalizado (para mejorar mi módulo de registro) o expandir todo mi código.
¿Alguien con mejores ideas? Además, WTF?
ACTUALIZACIÓN :
Gracias a las respuestas, he aprendido algo sobre cómo php hace el manejo de errores. La confusión de E_ALL que no incluye E_STRICT (php 5) no es buena.
Además de todo esto, la creación de su propio controlador de errores personalizado habilita E_STRICT de forma predeterminada y ahí es donde comienzan los problemas.
La moraleja de la historia es usar su propio controlador de errores para detectarlos TODOS y usar las constantes de error (E_STRICT, E_USER_WARNING, E_USER_ERROR, etc.) para realizar el filtrado.
En cuanto al ''problema de corrupción de memoria'' con referencias variables y ciertas funciones, ¿qué puedo decir? Doblemente uncool. Voy a (lo que no significa que debas) ignorar E_STRICT en mi controlador de errores y la vida continúa.
Creo que ahora (desde php 5) debería ser:
function &foo(){ //NOTICE THE &
$b=array_pop(array("a","b","c"));
return $b;
}
print_r(foo());
y
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());
pero solo soy un principiante :)
Es un problema de corrupción de memoria (según el equipo de desarrollo de PHP). Solo tira una tarea:
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());
El segundo produce un E_STRICT. Puede manejar eso de manera diferente en su controlador de errores si lo desea (si no desea cambiar esas funciones).
Esto es lo que obtengo cuando intento su segundo fragmento de código php en php-cli después de configurar error_reporting en 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
Como puede ver, aquí solo se aplican normas estrictas. Además, puede dejar que su controlador de errores personalizado los ignore (según el valor que obtenga: 2048, por ejemplo, aquí).
A partir de php 5.3, E_ALL no incluye E_STRICT, mira esto:
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
A partir de PHP 5.4, E_ALL
incluye 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
Prueba esto:
function foo(){
$a = array("a","b","c");
$b = array_pop($a);
return $b;
}
array_pop () intenta cambiar el valor que se pasa como parámetro. Ahora en su segundo ejemplo, este es el valor de retorno de array_slice (). En términos de motor, este es un "valor temporal" y dicho valor no puede ser pasado por referencias. Lo que necesitas es una variable temporal:
function foo(){
$a=explode( ''/'' , ''a/b/c'');
$b=array_slice($a,-2,1);
$c=array_pop($b);
return $c;
}
print_r(foo());
Luego se puede pasar una referencia a $ b a array_pop (). Vea http://php.net/references para más detalles sobre referencias.
Estándares estrictos de la misma pregunta : solo las variables deben pasarse por referencia , también https://bugs.php.net/bug.php?id=48937 .
array_pop()
cambia el valor que se le pasa, que es de donde viene el error. Una función no puede ser cambiada. En otras palabras, primero debe asignar la matriz a una variable (ref: manual ) y luego ejecutar array_pop()
.
El código que necesitas es este:
function foo(){
$a = array("a","b","c");
$b = array_pop($a);
return $b;
}
Edit: Ambas funciones que mencionaste tienen el mismo problema. Asigne la matriz a una variable y pase la variable a array_pop()
.