22 май 2021

Новые возможности PHP 8

#php, #php8

26 ноября 2020 года вышла новая мажорная версия php - PHP 8. С релиза семерки прошло почти 5 лет, за это время сообщество существенно изменилось и повзрослело. В том числе родилось большое количесвто идей и предложений по улучшению языка (rfc), часть из которых была реализована в восьмой версии. В этой статье я собираюсь рассмотреть наиболее значимые и полезные из них.

Новые возможности PHP 8

Property promotion

На мой взгляд это наиболее значительное и полезное новшество, позволяющее писать намного меньше кода при проектировании классов. Промоушн свойств добавляет в язык возможность инициализировать свойства и их значения прямо в конструкторе.

Было:
<?php

// Пример для php7
class User
{
    public string $name;
    public string $surname;
    public string $address;

    public function __construct(
        string $name,
        string $surname,
        string $address
    ) {
        $this->name = $name;
        $this->surname = $surname;
        $this->address = $address;
    }
}
Стало:
<?php

// Пример для php8
class User
{
    public function __construct(
        public string $name,
        public string $surname,
        public string $address,
    ) {}
}

Обратите внимание на запятую после $address в новом варианте - это тоже одно из усовершенствований, позволяющее писать более консистентный по стилю код.

Named properties

Именованные свойства позволяют передавать функции только те аргументы, которые необходимы, пропуская лишние. Например для функции setcookie нам надо было установить все аргументы, чтобы добраться до последнего $httponly, в том числе и не нужные нам: $secure и $expires.

Было:
<?php

// Пример для php7
setcookie('cookie', 'value', null, '/',null, false, true);
Стало:
<?php

// Пример для php8
setcookie('cookie', 'value', path: '/', httponly: true);;

Заметили в последнем примере использование именованных и обычных свойств? Такое использование возможно, если обычные идут вначале, иначе вы получите ошибку. Однако, будьте осторожны, смешивая разные типы аргументов, это совсем не улучшает читаемость.

Match

В php 8 нам добавили новое выражение match, которое пришло на замену весьма надоевшему switch. Оно мощнее, потому что использует строгое сравнение, не требует использования break и возвращает результат.

Было:
<?php

// Пример для php7
switch ('200') {
    case 200:
        echo 'OK';
        break;
    case 400:
        echo 'Not Found';
        break;
    default:
        echo "I don't know";
} // выведет OK
Стало:
<?php

// Пример для php8
echo match('200') {
    200 => 'OK',
    400 => 'Not Found',
    default => "I don't know",
}; // Выведет I don't know, потому что сравнение строгое

Match - это выражение, поэтому всегда должно заканчиваться точкой с запятой.

Nullsafe operator

Было:
<?php

// Пример для php7
$companyName = null;

if (!empty($user->company) ) {
    $companyName = $user->company->getName();
}
Стало:
<?php

// Пример для php8
$companyName = $user->company?->getName();

В первом примере, если company будет null, то вызов метода getName() вызовет ошибку, поэтому в этом месте приходится делать дополнительную проверку на !empty. А вот новая версия php позволяет использовать nullsafe operator (знак вопроса после company), который продолжит вычисления по цепочке, только если установлено company. В ином случае все дальнейшие действия не будут выполнены и оператор вернет null.

Сравнение строк с числами

Жонглирование типами в php очень часто приводило к неочевидным багам, поэтому было принято использовать строгое сравнение (тройное равно). Например:

// Пример для php7
'1' ==   1 // true
'1' ===  1 // false
'foo' == 1 // true

Поведение в последнем случае, скажем прямо, совсем не логично, однако для php всё выглядело правильно: слева непустая строка - значит true, справа число (не 0) - значит тоже true. В PHP 8 это поведение изменили:

// Пример для php8
'foo' == 1 // false

Теперь при сравнении с числовой строкой PHP использует сравнение чисел. Если не получается, то преобразует число в строку и сравнивает их как строки. Это поведение логично и предсказуемо. Однако, это не повод отказываться от строгого сравнения.

Функция str_contains

Мы её долго ждали, с момента создания языка. Какие только ухищрения не использовались для того, чтобы проверить содержится ли одна строка в другой: и strpos и strstr. В PHP 8 нам подарили:

str_contains (string $haystack , string $needle) : bool

Эта функция вернет простое булево значение при проверки наличии одной строки в другой.

Резюме

В новую восьмую версию php много полезных и удобных фичей и все их рассмотреть в рамках одной статьи непросто. Поэтому я остановился на самых важных нововведениях. Да, знаю, что атрибуты мы не рассмотрели - они заслуживают отдельной статьи. А полный список изменений можно посмотреть тут. Пользуйтесь новыми возможностями php и пишите классный код!

Полезные ссылки

Все статьи

© 2020-2021 Александр Пантелеев