Только переменные могут передаваться по ссылке

У меня была яркая идея использования специального обработчика ошибок, который привел меня к кроличьей дыре.

Следующий код дает (с и без специального обработчика ошибок): Фатальная ошибка: только переменные могут передаваться по ссылке

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

Следующий код дает ( только с помощью специального обработчика ошибок ): (2048) Только переменные должны передаваться по ссылке

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

Второй меня беспокоит, так как у меня много «компактного» кода. Таким образом, я либо бросаю яркую идею использования настраиваемого обработчика ошибок (для улучшения модуля регистрации), либо расширяю весь свой код.

Кто-нибудь с лучшими идеями? Кроме того, WTF?

ОБНОВЛЕНИЕ :

Благодаря ответам я кое-что узнал о том, как PHP обрабатывает ошибки. Путаница E_ALL, не считая E_STRICT (php 5), не крута.

Кроме всего прочего, создание собственного обработчика ошибок позволяет по умолчанию запускать E_STRICT, и в этом случае проблемы начинаются.

Мораль этой истории – использовать свой собственный обработчик ошибок, чтобы поймать их ВСЕ и использовать константы ошибок (E_STRICT, E_USER_WARNING, E_USER_ERROR и т. Д.), Чтобы сделать вашу фильтрацию.

Что касается «проблемы с коррупцией памяти» с переменными ссылками и некоторыми функциями, что я могу сказать? Совсем нераскрытый. Я (это не значит, что вам следует) игнорировать E_STRICT в моем обработчике ошибок, и жизнь продолжается.

array_pop () пытается изменить это значение, которое передается как параметр. Теперь в вашем втором примере это возвращаемое значение из array_slice (). В терминах двигателя это «временное значение», и такое значение не может быть передано по ссылкам. вам нужна временная переменная:

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

Тогда ссылка на $ b может быть передана array_pop (). См. http://php.net/references для получения дополнительной информации о ссылках.

Вот что я получаю при попытке выполнить второй фрагмент кода php в php-cli после установки error_reporting в 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 

Как вы можете видеть, здесь только строгие стандарты. И вы можете легко позволить своему пользовательскому обработчику ошибок игнорировать их (исходя из значения, которое вы получаете: 2048, например, здесь).

Начиная с php 5.3, E_ALL не включает E_STRICT, посмотрите на это:

 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 

Начиная с php 5.4, E_ALL включает 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 

Это проблема с повреждением памяти (согласно команде разработчиков PHP). Просто бросьте задание:

 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()); 

Второй создает E_STRICT. Вы можете обрабатывать это по-разному в своем обработчике ошибок, если хотите (если вы не хотите изменять эти функции).

array_pop() изменяет это значение, переданное ему, из которого происходит ошибка. Функция не может быть изменена. Другими словами, вам нужно сначала назначить массив переменной (ref: manual ), а затем запустить array_pop() .

Код, который вам нужен, следующий:

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

Изменить: обе функции, о которых вы упомянули, имеют одинаковую проблему. Назначьте массив переменной и передайте переменную array_pop() .

Я думаю, что теперь (начиная с php 5) это должно быть:

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

а также

 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()); 

но я просто начинающий 🙂

Попробуй это:

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

Тот же вопрос Строгие стандарты: только переменные должны передаваться по ссылке , а также https://bugs.php.net/bug.php?id=48937 .