PHP 5.4 Передача по ссылке во время разговора - легко ли исправить?

219

Есть ли способ легко решить эту проблему, или мне действительно нужно переписать весь старый код?

Неустранимая ошибка PHP: удалена ссылка на время вызова в ... в строке 30

Это происходит везде, когда переменные передаются в функции в виде ссылок по всему коду.

bardiir
источник

Ответы:

344

Вы должны обозначать вызов по ссылке в определении функции, а не фактический вызов. Поскольку PHP начал показывать ошибки устаревания в версии 5.3, я бы сказал, что было бы неплохо переписать код.

Из документации :

При вызове функции отсутствует ссылочный знак - только в определениях функций. Одних только определений функций достаточно, чтобы правильно передать аргумент по ссылке. Начиная с PHP 5.3.0, вы получите предупреждение о том, что «передача по времени вызова» не рекомендуется при использовании &в foo(&$a);.

Например, вместо использования:

// Wrong way!
myFunc(&$arg);               # Deprecated pass-by-reference argument
function myFunc($arg) { }

Использование:

// Right way!
myFunc($var);                # pass-by-value argument
function myFunc(&$arg) { }
Тим Купер
источник
9
Устаревание начиная с PHP 5.0.0, в то время давало E_COMPILE_WARNINGошибку уровня, для справки: php.net/manual/en/…
hakre
5
У меня была эта ошибка, но мне нужно было удалить & insted добавления в переменную.
Диана
2
Я использовал это в старом коде для объекта под названием событие (& $ event), и мне пришлось удалить амперсанд, чтобы сообщение об ошибке исчезло.
Наталья
1
За все годы работы разработчиком мне никогда не приходилось использовать & на php. никогда никогда это было именно то, что я искал. отлично
Хуан Вилар
8
для людей в комментариях обратите внимание, что удаление & может привести к неожиданным результатам, так как любые изменения в переменной больше не будут передаваться, а будут видны только локальной области функций. Поэтому, если вы не знаете, что делает код, я бы порекомендовал исправить его, как описано выше, вместо того, чтобы просто удалить символ &
xorinzor
8

Для тех, кто, как и я, читает это, потому что им нужно обновить гигантский унаследованный проект до 5.6: как показывают ответы здесь, быстрого решения не существует: вам действительно нужно найти каждое возникновение проблемы вручную и устранить ее. ,

Самый удобный способ, который я нашел, - найти все проблемные строки в проекте (если не использовать полнофункциональный статический анализатор кода, который очень точен, но я не знаю ни одного, который сразу же приведет вас к правильному положению в редакторе) использовала код Visual Studio, в который встроен красивый PHP-линтер, и функцию поиска, которая позволяет выполнять поиск по Regex. (Конечно, для этого вы можете использовать любой редактор IDE / Code, который выполняет PHP-линнинг и поиск в Regex.)

Используя это регулярное выражение:

^(?!.*function).*(\&\$)

можно выполнить поиск по всему проекту &$только в тех строках, которые не являются определением функции.

Это все еще вызывает много ложных срабатываний, но облегчает работу.

Браузер результатов поиска VSCode упрощает просмотр и нахождение оскорбительных строк: вы просто нажимаете на каждый результат и высматриваете те, которые выделены красной линией. Те, что вам нужно исправить.

Пекка
источник
1
Это то, что я искал!
Сонни
4
Более точное регулярное выражение, которое я использую для этой цели:(?<!function)[:> ][a-zA-Z0-9_]+(?<!foreach|array)\s?\([^()]*&\$
Mojo
просто используйте phpcs, выкопайте каждый файл, который имеет это для вас.
Томас Ченг
6

PHP и ссылки несколько не интуитивно понятны. При правильном использовании ссылки в нужных местах могут обеспечить значительное повышение производительности или избежать очень уродливых обходных путей и необычного кода.

Следующее приведет к ошибке:

 function f(&$v){$v = true;}
 f(&$v);

 function f($v){$v = true;}
 f(&$v);

Ни один из них не должен потерпеть неудачу, поскольку они могли следовать приведенным ниже правилам, но, без сомнения, были удалены или отключены, чтобы избежать путаницы в наследство.

Если они действительно работали, оба включали избыточное преобразование в ссылку, а второе также включало избыточное преобразование обратно в переменную, содержащуюся в области.

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

Это ничего не будет делать:

 function f($v){$v = true;}
 $r = &$v;
 f($r);

Более конкретно, он превращает ссылку обратно в обычную переменную, поскольку вы не запрашивали ссылку.

Это будет работать:

 function f(&$v){$v = true;}
 f($v);

Это означает, что вы передаете не-ссылку, но хотите ссылку, поэтому превращает ее в ссылку.

Это означает, что вы не можете передать ссылку на функцию, для которой ссылка явно не запрашивается, чтобы сделать ее одной из немногих областей, где PHP строг в отношении передачи типов или, в данном случае, в большей степени мета-типа.

Если вам нужно более динамичное поведение, это будет работать:

 function f(&$v){$v = true;}
 $v = array(false,false,false);
 $r = &$v[1];
 f($r);

Здесь он видит, что вы хотите ссылку и уже есть ссылка, поэтому оставляет его в покое. Это может также связать ссылку, но я сомневаюсь в этом.

jgmjgm
источник