Зміни, що ламають зворотну сумісність

Зміни в обробці помилок та винятків

Багато фатальних і виправних фатальних помилок було перероблено у винятки в PHP 7. Ці винятки успадковують клас Error, який, у свою чергу, реалізує інтерфейс Throwable (Новий базовий інтерфейс, який успадковують усі винятки).

Це означає, що користувальницькі обробники помилок можуть не бути викликані, тому що замість виклику помилки, буде викинуто виняток (породжуючи нові фатальні помилки через неперехоплені винятки класу Error

Більш детальний опис того, як помилки працюють у PHP 7, можна знайти на сторінці помилки PHP 7. Це керівництво лише перераховує зміни, які можуть призвести до зворотної несумісності.

set_exception_handler() більше не гарантує отримання об'єкта класу Exception

Код, реализующий регистрацию обработчика исключений с помощьюset_exception_handler(), используя декларацию типаException, викличе фатальну помилку, якщо буде викинуто виняток Error

Якщо потрібна робота оброблювача в PHP 5 і 7, ви повинні прибрати оголошення класу з оброблювача. Якщо код передбачається використовувати тільки в PHP 7, то можна просто змінити тип з ExceptionнаThrowable

Loading...

Вбудовані конструктори завжди викликають винятки у разі невдачі

Раніше деякі внутрішні класи повертали null або марний об'єкт, коли конструктор зазнав невдачі. Усі вбудовані класи тепер у такому разі викидатимуть виняток Exception, Як це вже роблять користувальницькі класи.

Ошибки разбора бросают исключение классаParseError

Ошибки разбора бросают исключение классаParseErrorОбработка ошибокeval() повинна включати блок catch, який ловитиме цю помилку.

Зміна суворості повідомлень E_STRICT

Всі повідомлення E_STRICT перекваліфіковані за іншими рівнями. Константа E_STRICT збережено, так що error_reporting(E_ALL|E_STRICT) не викликає помилки.

Зміна суворості повідомлень E_STRICT

СитуацияНовый уровень/поведение
Індексування ресурсомE_NOTICE
Абстрактні статичні методиПовідомлення прибрано, не викликає помилки
"Перевизначення" конструктораПовідомлення прибрано, не викликає помилки
Недотримання сигнатури при наслідуванніE_WARNING
Однакові (сумісні) властивості у двох різних трейтахПовідомлення прибрано, не викликає помилки
Нестатичний доступ до статичної властивостіE_NOTICE
Тільки змінні можуть бути присвоєні за посиланнямE_NOTICE
Тільки змінні можуть бути передані за посиланнямE_NOTICE
Виклик нестатичного методу статичноE_DEPRECATED

Зміни в обробці змінних

PHP 7 використовує абстрактне синтаксичне дерево для аналізу файлів з вихідним кодом. Це дозволило внести безліч покращень у мову, які раніше були неможливі через обмеження парсера, що використовувався в попередніх версіях PHP, але призвело до видалення деяких особливих можливостей з міркувань узгодженості та порушило зворотну сумісність. Опис цих особливих випадків наведено у цій секції.

Зміни в обробці непрямих змінних, властивостей та методів

Непрямий доступ до змінних, властивостей та методів тепер розкривається строго зліва-направо, на противагу попередньому поєднанню зі спеціальних правил. У таблиці подано зміни у порядку розкриття.

Стара та нова оцінка непрямих виразів

ВыражениеИнтерпретация PHP 5Интерпретация PHP 7
$$foo['bar']['baz']${$foo['bar']['baz']}($$foo)['bar']['baz']
$foo->$bar['baz']$foo->{$bar['baz']}($foo->$bar)['baz']
$foo->$bar['baz']()$foo->{$bar['baz']}()($foo->$bar)['baz']()
Foo::$bar['baz']()Foo::{$bar['baz']}()(Foo::$bar)['baz']()

Код, який використовує старий порядок розкриття справа-ліворуч, повинен бути переписаний з використанням фігурних дужок (дивіться середній стовпець у таблиці вище). Це зробить код робочим як у PHP 5.x, так і в PHP 7.x.

Також це стосується і ключового слова global. Для емуляції старої поведінки необхідно використовувати фігурні дужки:

Loading...

Изменение в обработкеlist()

list() більше не надає змінних у зворотному порядку

Тепер list() привласнює змінні тому порядку, як вони перераховані, а чи не у протилежному. Загалом це впливає тільки на випадки, коли list() використовується спільно з оператором масиву [], як показано нижче:

Loading...

Результат виконання наведеного прикладу в PHP 5:

array(3) {
  [0]=>
  int(3)
  [1]=>
  int(2)
  [2]=>
  int(1)
}

Результат виконання наведеного прикладу в PHP 7:

array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
}

Також хочеться відзначити, що покладатися на порядок присвоєння оператором list() - не самое разумное решение, поскольку он снова может поменяться в будущем.

Пустое присвоениеlist()больше не разрешено

Конструкцияlist() більше не може бути порожнім. Наступні приклади неприпустимі:

Loading...
list() не може розкривати рядки

list() більше не може розкривати рядки. Використовуйте str_split()

Змінено порядок масиву при автоматичному створенні через присвоєння за посиланням

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

Loading...

Результат виконання наведеного прикладу в PHP 5:

array(2) {
  ["b"]=>
  &int(1)
  ["a"]=>
  &int(1)
}

Результат виконання наведеного прикладу в PHP 7:

array(2) {
  ["a"]=>
  &int(1)
  ["b"]=>
  &int(1)
}

Дужки навколо аргументів функції більше ні на що не впливають

У PHP 5 під час використання надлишкових дужок навколо аргументів функції не виводилося попередження, коли аргумент передавався за посиланням. Тепер попередження завжди виводиться.

Loading...

Результат виконання наведеного прикладу:

Notice: Only variables should be passed by reference in /tmp/test.php on line 13

Измененияforeach

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

foreach більше не змінює внутрішній покажчик масиву

До PHP 7 в процессе итерации массива вforeach, його внутрішній покажчик змінювався. У прикладі нижче показано, що ця поведінка змінена:

Loading...

Результат виконання наведеного прикладу в PHP 5:

int(1)
int(2)
bool(false)

Результат виконання наведеного прикладу в PHP 7:

int(0)
int(0)
int(0)

foreach за значеннями оперує копією масиву

Якщо foreach використовується для стандартного перебору за значенням, він оперує копією масиву, а чи не самим масивом. Це означає, що зміни внесені в масив усередині циклу не торкнуться значення, що перебираються.

Дляforeach за посиланням покращили поведінку при ітерації

Когдаforeach використовується для перебору за посиланням, він краще відстежуватиме зміни, що вносяться в масив у процесі ітерації. Наприклад, додавання елементів до масиву, що ітерується, призведе до того, що ці нові елементи потраплять у перебір:

Loading...

Результат виконання наведеного прикладу в PHP 5:

int(0)

Результат виконання наведеного прикладу в PHP 7:

int(0)
int(1)

Ітерація об'єктів, що не реалізують Traversable

Ітерація об'єктів, що не реалізують Traversable тепер відбувається так само, як і ітерація масиву за посиланням. Так виходить через те, що покращення поведінки при зміні масиву під час ітерації також впливає при додаванні або видаленні властивостей об'єкта.

Зміна в обробці значень типу int

Некоректна вісімкова нотація

Раніше восьмеричні літерали, що містять некоректні числа, мовчки обрізалися (0128 вважалися за 012). Зараз у таких випадках буде видано помилку розбору.

Негативні побітові усунення

Тепер побітові зміщення на негативну величину кидатимуть виняток ArithmeticError :

Loading...

Результат виконання наведеного прикладу в PHP 5:

int(0)

Результат виконання наведеного прикладу в PHP 7:

Fatal error: Uncaught ArithmeticError: Bit shift by negative number in /tmp/test.php:2
Stack trace:
#0 {main}
  thrown in /tmp/test.php on line 2

Побітові усунення з виходом з допустимого діапазону

Побітові зміщення (в обох напрямках) за межі ширини типу int завжди повертатимуть 0. Раніше поведінка залежала від архітектури.

Зміна у розподілі на нуль

Раніше використання нуля як дільника в операціях поділу (/) або поділу за модулем (%) призводило до помилки рівня E_WARNING та поверненню значення false. Тепер оператор поділу повертає число з плаваючою точкою, що дорівнює +INF, -INF або NAN, як визначено в IEEE 754. Поділ по модулю замість помилки рівня E_WARNING викидатиме виняток DivisionByZeroError

Loading...

Результат виконання наведеного прикладу в PHP 5:

Warning: Division by zero in %s on line %d
bool(false)

Warning: Division by zero in %s on line %d
bool(false)

Warning: Division by zero in %s on line %d
bool(false)

Результат виконання наведеного прикладу в PHP 7:

Warning: Division by zero in %s on line %d
float(INF)

Warning: Division by zero in %s on line %d
float(NAN)

PHP Fatal error:  Uncaught DivisionByZeroError: Modulo by zero in %s line %d

Зміни у обробці рядків

Шістнадцяткові рядки більше не рахуються за числові

Рядки, що містять шістнадцяткові символи більше не рахуються за числові. Приклад:

Loading...

Результат виконання наведеного прикладу в PHP 5:

bool(true)
bool(true)
int(15)
string(2) "oo"

Результат виконання наведеного прикладу в PHP 7:

bool(false)
bool(false)
int(0)

Notice: A non well formed numeric value encountered in /tmp/test.php on line 5
string(3) "foo"

Используйте функциюfilter_var() для перевірки рядка на утримання шістнадцяткового числа та перетворення цього рядка до значення типу int:

Loading...

\u{ може викликати помилки

У зв'язку з додаванням нового синтаксису екранування кодів Unicode, рядки, що містять рядок \u{, що передує некоректній послідовності, може призвести до фатальної помилки. Для того, щоб цього уникнути, необхідно екранувати перший зворотний сліш.

Віддалені функції

call_user_method() і call_user_method_array()

Функції, оголошені застарілими у PHP 4.1.0 на користь call_user_func() і call_user_func_array(). Можливо, вам також буде цікаво розглянути можливість звернення до функцій через змінніи/или оператор...

Усі функції ereg*

Усі функції ereg видалено. Рекомендована альтернатива - PCRE

Псевдоніми mcrypt

Устаревшая функцияmcrypt_generic_end() була видалена на користь функції mcrypt_generic_deinit()

Крім цього, застарілі функції mcrypt_ecb() mcrypt_cbc() mcrypt_cfb() і mcrypt_ofb() були видалені на користь використання mcrypt_decrypt() з відповідною константою MCRYPT_MODE_*

Усі функції модуля mysql

Усі функції ext/mysql були вилучені. Для вибору іншого MySQL API дивіться розділ Вибір MySQL API

Усі функції модуля mssql

Усі функції ext/mssql були вилучені.

Псевдоніми intl

Застарілі псевдоніми datefmt_set_timezone_id() і IntlDateFormatter::setTimeZoneID() були видалені на користь datefmt_set_timezone() і IntlDateFormatter::setTimeZone()соответственно.

set_magic_quotes_runtime()

set_magic_quotes_runtime() та її псевдонім magic_quotes_runtime() були вилучені. Вони були оголошені застарілими в PHP 5.3.0 і втратили свій сенс з відмовою від магічних лапок в PHP 5.4.0.

set_socket_blocking()

Устаревший псевдонимset_socket_blocking() був видалений на користь stream_set_blocking()

dl() у PHP-FPM

Функцияdl() більше не можна використовувати в PHP-FPM. Однак вона збереглася в CLI і вбудованих SAPI.

Функції GDType1

Підтримка шрифтів PostScript Type1 видалена із модуля GD. Відповідно були видалені такі функції:

  • imagepsbbox()
  • imagepsencodefont()
  • imagepsextendfont()
  • imagepsfreefont()
  • imagepsloadfont()
  • imagepsslantfont()
  • imagepstext()

Замість них рекомендується використовувати шрифти TrueType та пов'язані з ними функції.

Видалені директиви INI-файлу

Віддалені можливості

Наступні INI-директиви були видалені, оскільки пов'язані з ними функції також були видалені:

  • always_populate_raw_post_data
  • asp_tags

xsl.security_prefs

Директиваxsl.security_prefs було видалено. Замість неї контролю налаштувань безпеки повинен викликатися метод XsltProcessor::setSecurityPrefs() лише на рівні кожного процесора.

Інші зміни, що стосуються зворотної сумісності

Нові об'єкти не можуть надаватися за посиланням

Результат оператораnew більше не може бути присвоєний змінною за посиланням:

Loading...

Результат виконання наведеного прикладу в PHP 5:

Deprecated: Assigning the return value of new by reference is deprecated in /tmp/test.php on line 3

Результат виконання наведеного прикладу в PHP 7:

Parse error: syntax error, unexpected 'new' (T_NEW) in /tmp/test.php on line 3

Некоректні імена класів, інтерфейсів та трейтів

Наступні імена не можна використовувати для класів, інтерфейсів та трейтів:

  • bool
  • int
  • float
  • string
  • null
  • true
  • false

Більше того, такі імена не повинні використовуватися. Вони не приведуть до помилки в PHP 7.0, але вони зарезервовані на майбутнє і мають вважатися застарілими.

  • resource
  • object
  • mixed
  • numeric

Видалені PHP-теги ASP та script

Видалено підтримку використання тегів ASP та script для визначення коду PHP.

Віддалені теги ASP та script

Открывающий тегЗакрывающий тег
<%%>
<%=%>
<script language="php"></script>

Видалено дзвінки з невідповідного контексту

Раніше визнані застарілими у PHP 5.6 статичні виклики нестатичних методів з невідповідного контексту тепер призведуть до того, що для методу, що викликається, змінна $this буде не визначено та буде виведено попередження.

Loading...

Результат виконання наведеного прикладу в PHP 5.6:

Deprecated: Non-static method A::test() should not be called statically, assuming $this from incompatible context in /tmp/test.php on line 8
object(B)#1 (0) {
}

Результат виконання наведеного прикладу в PHP 7:

Deprecated: Non-static method A::test() should not be called statically in /tmp/test.php on line 8

Notice: Undefined variable: this in /tmp/test.php on line 3
NULL

yield тепер право-асоціативний оператор

Конструкцияyield більше не вимагає обертання в дужки і є право-асоціативним оператором з пріоритетом між printи=>. Це може призвести до зміни поведінки:

Loading...

Дужки можуть бути використані для усунення неоднозначності у таких випадках.

Функції не можуть мати декілька параметрів з однаковими іменами

Більше не можна визначити кілька параметрів з однаковими іменами. Наприклад, така функція видасть помилку рівня E_COMPILE_ERROR :

Loading...

Функції, що працюють із аргументами, тепер повертають їх поточнізначения

func_get_arg() func_get_args() debug_backtrace() і трасування винятків повертають не вихідні передані значення, а поточні значення, які можуть бути змінені.

Loading...

Результат виконання наведеного прикладу в PHP 5:

1

Результат виконання наведеного прикладу в PHP 7:

2

Оператор switch більше не може мати декілька блоків default

Більше неможливо встановити більше одного блоку default в операторі switch. Наприклад, така конструкція видасть помилку E_COMPILE_ERROR :

Loading...

Видалено $HTTP_RAW_POST_DATA

$HTTP_RAW_POST_DATA больше не доступен. Вместо него используйте потокphp://input

Заборонені коментарі #в INI-файлах

Поддержка префикса комментария#в INI-файлах удалена. Используйте префикс замість нього. Ця зміна стосується як php.ini, так і файлів, що обробляються функціями parse_ini_file() і parse_ini_string()

Модуль JSON замінено на JSOND

Модуль JSON замінений на JSOND, що породжує три невеликі зворотні несумісності. Перше - числа не повинні закінчуватися на крапку (тобто 34. має бути замінено на 34.0или34). Друге – при використанні наукової нотації, експонента e не повинна слідувати відразу за десятковою точкою (тобто 3.e3 потрібно поміняти на 3.0e3или3e3). Третє - порожній рядок більше не вважається коректним JSON.

Помилки внутрішніх функцій при переповненні

Раніше вбудовані функції могли тихо обрізати числа, отримані при наведенні типу float до integer, якщо float був більшим, ніж здатний вмістити integer. Тепер же видаватиметься помилка E_WARNING та повертатися null

Виправлення для значень користувальницького оброблювача сесії, що повертаються.

Будь-які предикатні функції, реалізовані за допомогою користувальницьких обробників сесії та повертають **false**или-1, викликають фатальну помилку Якщо ці функції повернуть будь-яке значення, крім логічного, -1или , вони будуть вважатися завершеними з помилкою та викличуть попередження E_WARNING.

Порядок сортування однакових елементів

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

Зауваження :

Не покладайтеся на порядок однакових елементів, оскільки він може змінитися в будь-який час.

Зміна порядку обробки операторів break та continue

Оператори breakиcontinue поза циклом або керуючою структурою switch тепер обробляються під час компіляції, а не під час виконання, як це було раніше, тому видають помилки рівня E_COMPILE_ERROR

Mhash більше не є модулем

Модуль Mhash повністю інтегрований у модуль HashТаким образом, теперь нельзя определить доступность поддержки Mhash с помощью функцииextension_loaded(); замість неї використовуйте function_exists(). Крім того, Mhash більше не виводитиме за допомогою get_loaded_extensions() та подібних функцій.

declare(ticks)

Директиваdeclare(ticks) більше не проникає у різні модулі компіляції.