Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Новое в PHP 8.4

PHP 8.4 убрал много шаблонного кода из классов: методы get и set во многих случаях больше не нужны. Появились и новые функции для массивов. Всё из этого урока требует версии 8.4 или новее.

Хук set

Хук — код, который выполняется при чтении или записи свойства. Хук set получает новое значение в переменной $value:

<?php
 
class User
{
    public string $name {
        set => trim($value);
    }
 
    public function __construct(string $name)
    {
        $this->name = $name;
    }
}
 
$user = new User('  Анна ');
 
echo "[$user->name]"; // [Анна]

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

Хук get

Свойство с одним хуком get не хранит значение — оно вычисляется при каждом обращении:

<?php
 
class Rectangle
{
    public int $area {
        get => $this->width * $this->height;
    }
 
    public function __construct(public int $width, public int $height) {}
}
 
$box = new Rectangle(3, 4);
 
echo $box->area; // 12

Проверка в хуке

В полной записи хука — с фигурными скобками — можно проверить значение и отклонить его:

<?php
 
class Product
{
    public int $price {
        set {
            if ($value < 0) {
                throw new InvalidArgumentException('Цена не может быть отрицательной');
            }
 
            $this->price = $value;
        }
    }
}
 
$product = new Product();
$product->price = 250;
 
try {
    $product->price = -5;
} catch (InvalidArgumentException $e) {
    echo $e->getMessage(), ': ', $product->price;
}

Программа выведет Цена не может быть отрицательной: 250 — неверное значение не записалось.

Раздельная видимость

Свойство можно сделать открытым для чтения и закрытым для записи:

<?php
 
class Account
{
    public private(set) int $balance = 0;
 
    public function deposit(int $amount): void
    {
        $this->balance += $amount;
    }
}
 
$account = new Account();
$account->deposit(500);
 
echo $account->balance, "\n"; // 500
 
try {
    $account->balance = 1000000;
} catch (Error $e) {
    echo 'Изменить баланс снаружи нельзя';
}

В отличие от readonly, такое свойство можно менять сколько угодно раз — но только изнутри класса.

Метод сразу после new

Раньше выражение new приходилось брать в скобки. Теперь метод вызывают сразу:

<?php
 
class Text
{
    public function __construct(private string $value) {}
 
    public function upper(): string
    {
        return mb_strtoupper($this->value);
    }
}
 
echo new Text('привет')->upper(); // ПРИВЕТ

Новые функции для массивов

<?php
 
$prices = [120, 450, 90, 700];
 
echo array_find($prices, fn($price) => $price > 400), "\n";     // 450
echo array_find_key($prices, fn($price) => $price > 400), "\n"; // 1
echo array_any($prices, fn($price) => $price > 600) ? 'да' : 'нет', "\n"; // да
echo array_all($prices, fn($price) => $price > 100) ? 'да' : 'нет';       // нет
ФункцияЧто возвращает
array_find()Первый подходящий элемент или null
array_find_key()Ключ первого подходящего элемента
array_any()true, если подходит хотя бы один
array_all()true, если подходят все

Ещё в 8.4 появились mb_trim(), mb_ucfirst() и атрибут #[\Deprecated], которым помечают устаревшие функции.

Частая ошибка

Свойство с одним хуком get — вычисляемое, записать в него нельзя:

<?php
 
class Rectangle
{
    public int $area {
        get => $this->width * $this->height;
    }
 
    public function __construct(public int $width, public int $height) {}
}
 
$box = new Rectangle(3, 4);
 
try {
    $box->area = 100;
} catch (Error $e) {
    echo 'Площадь вычисляется, присвоить её нельзя';
}

Чтобы изменить площадь, меняют ширину или высоту. И помните о версии: на сервере с PHP 8.3 файл с хуками не запустится вовсе — проверьте php -v.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.