PHP 5.4 Проходження часу виклику під час посилання - доступне легке виправлення?


219

Чи є якийсь спосіб легко виправити цю проблему чи мені справді потрібно переписати весь застарілий код?

Фатальна помилка PHP: Передача посилань на час виклику була видалена у ... у рядку 30

Це відбувається скрізь, оскільки змінні передаються у функції як посилання у коді.


Відповіді:


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) { }


5
У мене була ця помилка, але мені потрібно було видалити & insted додати до змінної.
Діана

2
Я використовував це в старому коді для об'єкта під назвою подія (& $ подія), і мені довелося видалити амперсанд, щоб повідомлення про помилку зникло.
Наталія

1
за всі мої роки як розробник мені насправді ніколи не потрібно було використовувати & on php. ніколи. саме це я і шукав. чудово
Хуан Вілар

8
для людей у ​​коментарях зауважте, що видалення & може призвести до несподіваних результатів, оскільки будь-які зміни змінної більше не надаватимуться спільним, але будуть видимі лише для функцій локальної області. Тож якщо ви не знаєте, що робить код, я рекомендую виправити його, як описано вище, а не просто видаляти & символ
xorinzor

8

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

Найзручніший спосіб я знайшов усі проблемні рядки в проекті (окрім використання повнорозмірного аналізатора статичного коду, який дуже точний, але я не знаю жодного, який би відразу перевів вас до правильного положення в редакторі) використовував Visual Studio Code, у якому вбудований хороший ліній PHP, та його функцію пошуку, яка дозволяє здійснювати пошук за допомогою Regex. (Звичайно, ви можете використовувати будь-який редактор IDE / коду для цього, який виконує зв'язок 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);

Тут видно, що ви хочете посилання і вже маєте посилання, тому залишає його в спокої. Він також може посилатися на посилання, але я сумніваюся в цьому.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.