Зміни, що ламають зворотну сумісність
Зміни в обробці помилок та винятків
Багато фатальних і виправних фатальних помилок було перероблено у винятки в 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) більше не проникає у різні модулі компіляції.