PHP 5.3 и присвоение возвращаемого значения new по ссылке

Назначение возвращаемого значения new по ссылке было deprecated в PHP 5.3. Таким образом,

$obj =& new Foo();

теперь выдает ошибку E_DEPRECATED.

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

Как потенциальное решение этой проблемы, я рассматриваю использование регулярного выражения для поиска и замены всех экземпляров =& new на = new. Например, следующее найдет все файлы PHP и уничтожит все экземпляры =& new:

find ./ -name '*.php' | xargs perl -p -i -e 's/=(\s*)&(\s*)?new\b/= new/g'

Ищете ответы на следующие вопросы:

  • Будет ли это работать отлично? С какими потенциальными проблемами я могу столкнуться?
  • Если нет, примеры кода, в которых замена =& new на = new изменит поведение в PHP 5.3.
  • Любые примеры популярных библиотек с этим, как известно, вызовут проблему.
  • Какие еще идеи вы рекомендуете решать с фиксацией огромных количеств =& new?

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

Ответ 1

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

Использование =& имеет эти различия с =:

  • =& попытается сделать правильную сторону ссылкой; = не будет - даже если правая сторона может дать ссылку, как функция, которая возвращается по ссылке.
  • =& сломает старый набор ссылок и поместит левую и правую стороны как в новую, а = изменит значение всех элементов в том же наборе ссылок, что и левая сторона, на значение с правой стороны.

Первое различие и половина второго в этом случае не имеют значения. После назначения будет только одна переменная со значением нового объекта *, а одноэлементные наборы ссылок не имеют смысла. Однако факт, что =& нарушает предыдущий набор ссылок, является значительным:

<?php

$g = 4;
$v =& $g;
$v = new stdclass();
var_dump($g); // object(stdClass)#1 (0) { }

$g = 4;
$v =& $g;
$v =& new stdclass();
var_dump($g); // int(4)

* Если, возможно, конструктор не протекает ссылка, но даже если он протекает, $this внутри конструктора может быть другой переменной, даже если он указывает на тот же объект. Поэтому я сомневаюсь, что из-за этого можно наблюдать разницу в поведении.

Ответ 2

Да, вы должны просто заменить =& new на = new. Объекты передаются по ссылке по умолчанию в PHP 5.3, поэтому никакое поведение не изменится.

+1 для фиксации уведомлений вместо их скрытия.

Ответ 3

Не должно быть никаких проблем. В худшем случае это немного замедлит ваше приложение на PHP 4, но оно определенно не изменит функциональность.

Единственная проблема, с которой вы могли теоретически столкнуться, заключается в том, что кто-то написал строку =& new в строке. Я знаю, это очень маловероятно, но если вы хотите заменить действительно только все вхождения '=' T_WHITESPACE? '&' T_WHITESPACE? T_NEW, вы должны сделать это, используя Tokenizer.