PHP 7.3: Головні нововведення
PHP 7.3 у гілці 7.x — реліз шліфування та безпеки: зручніший повсякденний синтаксис (гнучкий heredoc/nowdoc, кінцеві коми в викликах, посилання в list() / деструктуризації []), дрібні, але корисні функції (array_key_first(), array_key_last(), is_countable(), hrtime()) і оновлення платформи (JSON_THROW_ON_ERROR / JsonException, PASSWORD_ARGON2ID, PCRE2, великі зміни в mbstring). Під час міграції варто окремо перевірити розбір рядків (тіло heredoc проти закривальної мітки, класи символів PCRE), семантику посилань (читання з масиву/властивості, рядкові ключі ArrayAccess) і розширення (дроби секунд у MySQL, політика IMAP, імена cookie з 7.3.23).
Зміст
- Гнучкий Heredoc і Nowdoc
- Кінцеві коми у викликах функцій і методів
- Присвоєння за посиланням у
list()та[] instanceofз літераламиCompileError- Нові та оновлені помічники ядра
- JSON:
JSON_THROW_ON_ERRORіJsonException - Хешування паролів: Argon2id
- Важливі зміни розширень і stdlib
- Практичні рецепти
- Зворотно несумісні зміни (міграційні нотатки)
- Deprecated (виправити завчасно)
- Інші зміни та експлуатація (збірка, INI, продуктивність)
Гнучкий Heredoc і Nowdoc
Закривальну мітку можна відступити від краю рядка; такий самий відступ знімається з усіх рядків тіла. SQL, HTML і довгі тексти стають читабельнішими в коді з відступами.
Міграція: якщо всередині літерала трапляється той самий токен, що й мітка закриття (з урахуванням відступу), PHP може завершити рядок передчасно — обирайте довгі унікальні мітки (SQL_GET_USER, а не SQL).
$query = <<<SQL
SELECT id, name
FROM users
WHERE active = 1
SQL;
Кінцеві коми у викликах функцій і методів
У виклику після останнього аргумента дозволена зайва кома — зручно для багаторядкових diff і згенерованих списків аргументів:
$this->logger->info(
'User saved',
[
'id' => $user->id,
'ip' => $request->ip(),
],
);
Йдеться саме про виклики; не плутайте з оголошенням параметрів функцій в інших версіях PHP.
Присвоєння за посиланням у list() та []
Деструктуризація підтримує посилання:
[&$head, $middle, &$tail] = $parts;
list(&$a, $b) = $pair;
Використовуйте свідомо, коли треба змінювати спільну структуру; інакше краще звичайні значення.
instanceof з літералами
Зліва може бути літерал — результат завжди false. Це насамперед для узгодженості та статичного аналізу, не для бізнес-логіки.
CompileError
З’явився CompileError; від нього наслідується ParseError. На практиці це помітно в token_get_all($code, TOKEN_PARSE) і в інструментах: частина ситуацій замість fatal може приходити як виняток.
Нові та оновлені помічники ядра
array_key_first()/array_key_last()— без обхідних шляхів черезreset()/end()(для порожніх масивів див. мануал).is_countable($value)—trueдля масивів і об’єктів зCountable.hrtime($as_number = false)— монотонний час із високою роздільністю; для інтервалів зручніше за «календарний» wall-clock.net_get_interfaces()— перелік мережевих інтерфейсів (залежить від ОС).
JSON: JSON_THROW_ON_ERROR і JsonException
Прапорець JSON_THROW_ON_ERROR для json_encode / json_decode дає JsonException замість ланцюжка json_last_error(). Якщо разом з JSON_PARTIAL_OUTPUT_ON_ERROR, пріоритет у останнього.
$data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
Хешування паролів: Argon2id
За збірки з відповідною libargon2 доступна PASSWORD_ARGON2ID для password_hash() і пов’язаних функцій — реальна наявність залежить від дистрибутива та прапорів збірки.
Важливі зміни розширень і stdlib
- PCRE: рушій PCRE2 — можливі тонкі відмінності;
preg_quote()екранує також#. - mbstring: Unicode 11, рядки >2 ГБ, швидші регістронезалежні операції; case-folding; іменовані групи в
mb_ereg_*ближче до стилю PCRE (перевірте легасі-код). - LDAP: підтримка controls у пошуку/модифікації та
ldap_parse_result(). - MySQLi / PDO MySQL: у результатах native prepare можуть з’явитися дроби секунд для
DATETIME(6)/TIMESTAMP(6). - FPM: параметри логів;
getallheaders()доступна під FPM. - Сесії та cookie:
session_set_cookie_params(array), INIsession.cookie_samesite;setcookie/setrawcookieз масивом опцій, зокремаsamesite. - Потоки: IPv6 у
stream_socket_get_name()у квадратних дужках (наприклад[::1]:1337). - SPL autoload: якщо автозавантажувач кидає виняток, наступні не викликаються (раніше ланцюжок поводився інакше).
- IMAP: rsh/ssh за замовчуванням вимкнено — вмикайте лише свідомо (
imap.enable_insecure_rsh).
Практичні рецепти
Перед count()
if (is_countable($rows)) {
$n = count($rows);
}
Перший і останній ключ
$firstKey = array_key_first($map);
$lastKey = array_key_last($map);
Суворий JSON
try {
$payload = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
// обробка або обгортка
}
Інтервал із високою роздільністю
$t0 = hrtime(true);
// ...
$elapsedNs = hrtime(true) - $t0;
Зворотно несумісні зміни (міграційні нотатки)
Ядро
- Гнучкий heredoc/nowdoc: збіг із міткою закриття всередині тіла — ризик помилки розбору або зміни змісту; перейменуйте мітку або перепишіть текст.
continueуswitch: тепер попередження (у PHP це еквівалентноbreak, в інших мовах очікували бcontinue 2). Перевірте всіswitch+continue.ArrayAccessі рядкові «числові» ключі: для літерала"123"немає неявного приведення до int — викликаєтьсяoffsetGet("123"), а неoffsetGet(123). Звичайні масиви не змінюються.- Статичні властивості та посилання: не можна «розділити» успадковане статичне поле присвоєнням посилання між класами — закрито в реалізації.
- Посилання з ланцюжків
[]/->: посилання негайно згортаються; проміжні трюки з «підвішеним» посиланням не працюють. - Розгортання
...$traversable: для ітераторів із нецілими ключами розгортання не підтримується (у 7.2 частина випадків працювала випадково). - Винятки з режиму
EH_THROW: не заповнюютьerror_get_last(). TypeError: у тексті типиint/bool, неinteger/boolean.compact(): неоголошені імена дають notice.getimagesize()і подібні: BMP — MIMEimage/bmp, неimage/x-ms-bmp.- Cookie (з PHP 7.3.23): імена вхідних cookie не URL-декодуються.
BCMath
- Попередження йдуть через стандартний error handler, а не прямий запис у stderr.
bcmul()/bcpow()суворіше дотримуються scale (хвостові нулі можуть відрізнятися від старої поведінки).
IMAP
- rsh/ssh вимкнено за замовчуванням; з недовіреними іменами скриньок це критично, якщо увімкнете знову.
mbstring regex
- Іменовані групи змінюють склад
$matchesі підстановки вmb_ereg_replace().
MySQLi і PDO MySQL
- Дроби секунд можуть «спливти» в інтеграційних тестах на точне рядкове представлення часу.
Reflection
- У текстовому виводі —
int/bool.
SimpleXML
- Арифметика з текстовими вузлами обирає int/float адекватніше, ніж раніше.
Інше
- Підтримку BeOS знято;
ext_skelпереписано (авторам розширень — оновити скрипти). - Формат IPv6 у
stream_socket_get_name()з квадратними дужками.
Deprecated (виправити завчасно)
- Регістронезалежні
define()та звернення до константи в іншому регістрі, ніж оголошення. - Функція
assert()у просторі імен — не оголошуйте. - Нерядковий needle у сімействі
strpos— явний(string)абоchr(). fgetss,gzgetss,SplFileObject::fgetss, фільтрstring.strip_tags.FILTER_FLAG_SCHEME_REQUIRED/FILTER_FLAG_HOST_REQUIREDдляFILTER_VALIDATE_URL.image2wbmp().Normalizer::NONEпри ICU ≥ 56.- Аліаси
mbereg_*→mb_ereg_*. - INI
pdo_odbc.db2_instance_nameформально deprecated.
Повний перелік: migration73 deprecated.
Інші зміни та експлуатація
- Syslog INI:
syslog.facility,syslog.filter,syslog.ident; з 7.3.8 фільтрrawвідновлює старе агресивніше логування. - Збирання циклів (GC): покращення — профілі пам’яті/часу довгоживучих воркерів можуть зміститися.
var_export()дляstdClassчерез(object) array (...).- FTP: режим за замовчуванням — binary.
- FILTER_VALIDATE_FLOAT: опція
thousandдля роздільників тисяч. - OpenSSL:
min_proto_version/max_proto_versionдля потоків. - PDO SQLite: лише читання через
PDO::SQLITE_ATTR_OPEN_FLAGS. - XML: значення, що повертає обробник зовнішніх сутностей, враховується при збірці з libxml.
- cURL: потрібна libcurl ≥ 7.15.5.
- OPcache: прибрано
opcache.inherited_hack. - ODBC: прибрано Birdstep / ODBCRouter.
Підсумок
Сфокусуйте рев’ю на continue+switch, compact(, реалізаціях ArrayAccess, heredoc-мітках та ...$iterator. Прогоніть тести з регулярними виразами та датою/часом, далі плануйте 7.4 — там уже typed properties і ширший крок; чим раніше приберете deprecations 7.3, тим спокійніша наступна міграція.