Подтвердить что ты не робот

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

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

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

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?

UPDATE

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

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

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

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

4b9b3361

Ответ 1

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.

Ответ 2

Вот что я получаю при попытке выполнить второй фрагмент кода php в php-cli после установки error_reporting в E_ALL | E_STRICT

    [email protected]:~/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

Ответ 3

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

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. Вы можете обрабатывать это по-разному в своем обработчике ошибок, если хотите (если вы не хотите изменять эти функции).

Ответ 4

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

Код, который вам нужен, это:

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

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

Ответ 5

Я думаю, что теперь (начиная с 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());

но я просто начинаю:)

Ответ 6

Попробуйте следующее:

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