Eloquent: Аксессоры и Мутаторы в примерах

Источник: «Eloquent Accessors and Mutators: Three Examples (Laravel 9+ vs Laravel 8)»
При работе с моделями часто нужно сделать что-то с данными до или после их сохранения в базе данных: изменить формат, обрезать пробелы, вырезать HTML-тэги и так далее.

Для этого можно использовать Eloquent Аксессоры и Мутаторы.

Этого можно добиться двумя различными способами из-за изменений синтаксиса внесённого в Laravel 9. Давайте рассмотрим три реальных и разных примера:

Пример 1. Только получение данных

В этом примере у нас самый распространённый сценарий, когда в базе есть два поля — first_name и last_name, и мы должны объединить их, например, в $user->full_name:

Пример кода Laravel 9+

app/Models/User.php:

use Illuminate\Database\Eloquent\Casts\Attribute;

// ...

public function fullName(): Attribute
{
return new Attribute(
get: fn () => $this->first_name .' ' . $this->last_name
);
}

Пример кода Laravel 8

app/Models/User.php:

public function getFullNameAttribute(): string
{
return $this->first_name .' ' . $this->last_name;;
}

Как видите, в Laravel 9 появился новый класс Attribute используемый для определения Аксессора.

Обратите внимание, что имя метода — camelCase (fullName), а сам атрибут — snake_case (full_name).

Пример 2. Только установка данных

В этом примере мы предположим, что пользователи могут вводить HTML содержимое, и мы хотим разрешить сохранение в базе данных определённых тегов, таких как <a> и <p>. Мы будем использовать функцию strip_tags для удаления всех остальных тэгов:

Пример кода Laravel 9+

app/Models/Post.php:

use Illuminate\Database\Eloquent\Casts\Attribute;

// ...

public function description(): Attribute
{
return new Attribute(
set: fn($value) => strip_tags($value, '<a><p>')
);
}

Пример кода Laravel 8

app/Models/Post.php:

public function setDescriptionAttribute($value): void
{
$this->attributes['description'] = strip_tags($value, '<a><p>');
}

Пример 3. Получение и установка данных

В этом примере мы получим и сохраним поле. Мы будем использовать сильно упрощённый конвертор валют, для сохранения введённой суммы, как int в базе данных и возвращения её, как float в пользовательский интерфейс:

Пример кода Laravel 9+

app/Models/Product.php:

use Illuminate\Database\Eloquent\Casts\Attribute;

// ...

public function price(): Attribute
{
return new Attribute(
get: fn($value) => $value / 100,
set: fn($value) => $value * 100
);
}

Пример кода Laravel 8

app/Models/Product.php:

public function getPriceAttribute($value): int
{
return $value / 100;
}

public function setPriceAttribute($value): void
{
$this->attributes['price'] = $value * 100;
}

С обоими геттерами и сеттерами становится более очевидным, что мы пишем гораздо больше кода старым способом Laravel 8, выполняя то же самое, что и в Laravel 9 или 10.

Дополнительные материалы

Предыдущая Статья

Laravel: Рекомендации на 2023 год. Полное руководство

Следующая Статья

Laravel: CI с GitHub Actions