PHP 7.0: Головні нововведення

PHP 7.0 завершує епоху «п’ятірок»: з’являються скалярні оголошення типів (типово — coercive, а strict_types=1 увімкують свідомо), типи, що повертаються, оператори ?? та <=>, анонімні класи, Closure::call(), конструкція yield from і явний return у генераторі з читанням через Generator::getReturn(), функція intdiv(), random_bytes() / random_int() для криптостійких випадковостей, фільтрований unserialize() і preg_replace_callback_array().

Під капотом багато колишніх fatal перетворюються на Error, TypeError, ParseError у спільній ієрархії Throwable. Якщо глобальний обробник очікує лише Exception, перший TypeError може зірвати обробку запиту — варто оновити сигнатури та стратегію логування.

Зміст


Скалярні типи й strict_types

До параметрів додаються string, int, float, bool поряд із класами, array, callable. Без declare(strict_types=1); PHP лишається «пом’якшеним»: рядок "10" може стати int. Увімкнули суворість — невідповідність одразу TypeError.

declare(strict_types=1);

function increment(int $x): int {
    return $x + 1;
}

Типи повернення

Оголошений тип результату перевіряється під час виконання; void і пов’язані правила з’являються в 7.1.

Оператор ??

$name = $_GET['name'] ?? 'guest';

Не породжує notice для відсутніх індексів — зручніше за каскади isset.

Оператор <=>

Повертає -1 / 0 / 1 — ідеально для usort і власних компараторів.

usort($rows, function ($a, $b) {
    return $a['score'] <=> $b['score'];
});

Анонімні класи

$logger = new class implements LoggerInterface {
    public function log($level, $message, array $context = []) { /* … */ }
};

Closure::call()

$getter = function () { return $this->value; };
$getter->call($object);

Генератори

yield from делегує іншому iterable; return $x; після завершення доступний через getReturn().

intdiv(), CSPRNG, unserialize

  • intdiv: цілочисельне ділення, /0ArithmeticError.
  • random_bytes / random_int: криптостійкі значення між ОС.
  • unserialize(..., ['allowed_classes' => [...]]): білий список класів.

Груповий use

use Foo\Bar\{Baz, Qux};

Практичні рецепти

$limit = (int) ($_GET['limit'] ?? 25);
usort($items, function ($a, $b) {
    return strcmp($a['id'], $b['id']);
});

Зворотна несумісність

Повна картина — migration70 incompatible. Короткий чеклист:

Помилки

  • Throwable; багато fatalError.
  • set_exception_handler(Exception $e) небезпечний — потрібен Throwable або без типу.

Синтаксис і змінні

  • Вирази на кшталт $$foo['bar']['baz'] читаються зліва направо; для старої семантики PHP 5 потрібні {} з мануала.
  • list(): порядок присвоєння за оголошенням змінних; порожній list() заборонено; рядок через list() не розпаковується.

Масиви й foreach

  • Інша поведінка внутрішнього покажчика і копії при ітерації за значенням.
  • Зайві дужки біля аргумента-by-ref більше не «прибирають» попередження.

Рядки й числа

  • Шістнадцяткові рядки "0x…" не підхоплюються як числа автоматично.
  • Складні "${...}" у подвійних лапках — перегляньте шаблони.

Текст UTF-8

  • substr/strlen — у байтах; для користувацького тексту додавайте mb_*.

Що прибрали з поставки

mysql_*, ereg_*, низка SAPI — migration70 removed. Заміна: mysqli/PDO, preg_*.

Deprecated

Конструктори як ім’я класу, статичні виклики не-static методів, ручна сіль у password_hash, ldap_sort, capture_session_metamigration70 deprecated.

Інші нотатки

assert і zend.assertions, зміни JSON, зникнення split()preg_split/explode.


Підсумок

5.x → 7.0 — окремий проєкт: прибрати mysql/ereg, додати catch (Throwable $e), прогнати регресію list()/foreach. Далі мінори 7.1+ крокують спокійніше.