PHP 7.x

Что нам даёт семёрка и что будет завтра

Александр Макаров

Yii core team

http://slides.rmcreative.ru/2017/devconf-php7/

Что происходит с PHP?

Сейчас, наконец, стал актуален PHP 7.*

На него собираются мигрировать все большие фреймворки:
Symfony, Zend, Yii, Laravel.

  • Заметно быстрее.
  • Лучше работает с объектами.
  • Меньше кушает памяти.
  • Практически не течёт.
  • Мощнее в плане возможностей.

Никуда не собирается деваться.

Итак, что же занятного в семёрке?

5.6 → 7.0

Скорость!

phpng рулит! От 5% до 70% прироста без изменения кода.

Память

Раньше ещё имелся смысл использовать массивы вместо объектов из соображений экономии. Теперь его почти нет. Семёрка кушает вдвое меньше.

Многие фаталы стали исключениями

  • Наследуются от \Error или \ParseError.
  • Ловятся try-catch.
  • Портят жизнь авторам фреймворков.

Расширен набор исключений:

  • Throwable.
  • Error.
  • TypeError.
  • ParseError.
  • AssertionError.
  • ArithmeticError.
  • DivisionByZeroError.

Массивы

intl довели до нормального состояния

Раньше приходилось писать polyfill-ы.

Скалярные тайпхинты

  • string, int, float, bool.
  • Работают в двух режимах: строгом (declare(strict_types=1)) и нет.

// Coercive mode
function sumOfInts(int ...$ints)
{
    return array_sum($ints);
}

var_dump(sumOfInts(2, '3', 4.1));
                    

Строгость позволяет выловить целый класс ошибок на этапе написания кода.

Декларация возвращаемых значений


function arraysSum(array ...$arrays): array
{
    return array_map(function(array $array): int {
        return array_sum($array);
    }, $arrays);
}

print_r(arraysSum([1,2,3], [4,5,6], [7,8,9]));

Слишком строгая :(

null нельзя.

null coalescing


$username = $_GET['user'] ?? 'nobody';
// то же, что и
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
// можно и так:
$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';
                    

Летающая тарелка


echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1

https://wiki.php.net/rfc/combined-comparison-operator

Пользуетесь?

Анонимные классы


$app = new Application;
$app->setLogger(new class implements Logger {
    public function log(string $msg) {
        echo $msg;
    }
});
                    

Нужно редко. Лучше не увлекаться.

escape-синтаксис для юникода


echo "\u{aa}";
echo "\u{0000aa}";
echo "\u{9999}";
                    

Очень удобно.

Closure::call($newthis, ...)

Временно привязывает замыкание к объекту и вызывает его с параметрами.

Этим можно делать хаки вроде гидрации.


class Value {
    protected $value;

    public function __construct($value) {
        $this->value = $value;
    }

    public function getValue() {
        return $this->value;
    }
}

$three = new Value(3);
$closure = function ($delta) { var_dump($this->getValue() + $delta); };
$closure->call($three, 4);

Опции из php.ini при старте сессий


session_start([
    'cache_limiter' => 'private',
    'read_and_close' => true,
]);
                    

Безопасность

  • random_bytes().
  • random_int().
  • Запретили генерить свою соль и передавать в password_hash().

Можно не париться :)

assert() expectations

Проверки для отладки, разработки и тестов. Не влияют на продакшн (zend.assertions, php.ini).


assert(true == false);

Хорошая альтернатива строгим проверкам всего и выкидыванию исключений.

Ослабили ограничения на зарезервированные слова


// 'new', 'private', and 'for' were previously unusable
Project::new('Project Name')->private()->for('purpose here')->with('username here');
                    

Привет, приятные DSL!

И ещё всякое

  • Группировка use.
  • return и делегирование для генераторов.
  • Deprecate-нули конструкторы PHP4.
  • Deprecate-нули статические вызовы нестатических методов.
  • Opcache всегда кеширует и отдаёт phpdoc.
  • getenv() научился не учитывать SAPI.

7.0 → 7.1

Ещё немного быстрее

nullable types


function testReturn(): ?string
{
return 'elePHPant';
}

Ура!

void для возвращаемых значений

Запрещает возвращать что либо из функции.

https://wiki.php.net/rfc/void_return_type

object как тайпхинт


function acceptsObject(object $obj) {
    ...
}
                    

Иногда может быть полезно. Например, сериализация.

Короткий list() и ключи


    $data = [
        ["id" => 1, "name" => 'Tom'],
        ["id" => 2, "name" => 'Fred'],
    ];

    [$id1, $name1] = $data[0];

    foreach ($data as [$id, $name]) {
        // logic here with $id and $name
    }

    ["id" => $id1, "name" => $name1] = $data[0];

    foreach ($data as ["id" => $id, "name" => $name]) {
        // logic here with $id and $name
    }

Области видимости для констант


class ConstDemo
{
    const PUBLIC_CONST_A = 1;
    public const PUBLIC_CONST_B = 2;
    protected const PROTECTED_CONST = 3;
    private const PRIVATE_CONST = 4;
}
                    

О, да! https://wiki.php.net/rfc/class_const_visibility

iterable


function iterator(iterable $iter)
{
    foreach ($iter as $val) {
        //
    }
}
                    

https://wiki.php.net/rfc/iterable

Раньше надо было проверять is_array() && instanceof \Traversable.

Несколько catch


try {
    // some code
} catch (FirstException | SecondException $e) {
    // handle first and second exceptions
}
                    

Просто немного удобней.

А также

7.1 → 7.2

Больше скорости!

Дмитрий Стогов не дремлет!

Можно убирать тайпхинты при наследовании

https://wiki.php.net/rfc/parameter-no-type-variance

Можно перекрыть абстрактный метод абстрактным методом

https://wiki.php.net/rfc/allow-abstract-function-override

Зачем?!

Меньше глупых ошибок

Argon2i и libsodium

Можно использовать в password_hash() и password_verify().

Libsodium — более простая и понятная альтернатива mcrypt и openssl.

Возможно будет в 7.2

Null Coalescing Assignment



$this->request->data['comments']['user_id'] =
    $this->request->data['comments']['user_id'] ?? 'value';

↓

$this->request->data['comments']['user_id'] ??= 'value';
                    

Стоит ли обновляться?

Да!

Добивайтесь этого как только можете.

Какую версию выбрать?

Практически все большие фреймворки переходят на 7.1.

Время вопросов!