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

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

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

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 в моем обработчике ошибок, и жизнь продолжается.

17
задан zaf 4 June 2010 в 07:55
поделиться

5 ответов

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

4
ответ дан 30 November 2019 в 12:13
поделиться

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

Вам нужен следующий код:

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

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

1
ответ дан 30 November 2019 в 12:13
поделиться

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

function foo(){
    $a = array("a","b","c");
    $b = array_pop($a);
    return $b;
}
0
ответ дан 30 November 2019 в 12:13
поделиться

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 для получения дополнительной информации о ссылках.

18
ответ дан 30 November 2019 в 12:13
поделиться

Вот что я получаю при попытке вашего второго фрагмента кода 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
9
ответ дан 30 November 2019 в 12:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: