Событие saving
Событие saving относится к модели Eloquent и вызывается непосредственно перед тем, как модель будет сохранена в базу данных. Это событие срабатывает как при создании новой записи, так и при обновлении существующей. Оно позволяет выполнить различные операции, например, валидацию данных, нормализацию полей или установку дополнительных атрибутов. Событие saving является частью системы событий Eloquent и может быть перехвачено с помощью наблюдателей или замыканий.
Особенность события saving заключается в том, что оно выполняется до всех остальных операций сохранения. Если в обработчике вернуть false, то операция сохранения будет отменена, и модель не будет сохранена в базу данных.
Синтаксис
Событие saving можно зарегистрировать несколькими способами:
<?php
// В загрузочном методе модели
protected static function booted(): void
{
static::saving(function ($model) {
// Выполняется перед сохранением
});
}
// В сервис-провайдере
use App\Models\Article;
Article::saving(function ($model) {
// Выполняется перед сохранением
});
// В наблюдателе
class ArticleObserver
{
public function saving(Article $article): void
{
// Выполняется перед сохранением
}
}
?>
Пример с простым использованием
Рассмотрим базовый пример использования события saving для автоматической установки поля 'slug' перед сохранением статьи:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
protected static function booted(): void
{
static::saving(function ($model) {
if (empty($model->slug)) {
$model->slug = str_replace(' ', '-', $model->title);
}
});
}
}
?>
После сохранения статьи с пустым полем 'slug':
<?php
use App\Models\Article;
$article = new Article();
$article->title = 'My First Article';
$article->save();
echo $article->slug;
?>
Результат выполнения кода:
"My-First-Article"
Пример с валидацией данных
Событие saving можно использовать для проверки данных перед сохранением. Если данные не проходят валидацию, можно отменить сохранение:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected static function booted(): void
{
static::saving(function ($model) {
if (strlen($model->name) < 3) {
return false; // Отмена сохранения
}
});
}
}
?>
Попытка сохранить пользователя с коротким именем:
<?php
use App\Models\User;
$user = new User();
$user->name = 'Jo';
$res = $user->save();
echo $res ? 'Saved' : 'Not saved';
?>
Результат выполнения кода:
"Not saved"
Пример с нормализацией данных
Событие saving позволяет нормализовать данные перед сохранением, например, привести строки к определенному формату:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
protected static function booted(): void
{
static::saving(function ($model) {
$model->title = trim($model->title);
$model->content = trim($model->content);
if ($model->isDirty('title')) {
$model->slug = str($model->title)->slug();
}
});
}
}
?>
Сохранение статьи с пробелами в заголовке и содержимом:
<?php
use App\Models\Article;
$article = new Article();
$article->title = ' My Article ';
$article->content = ' Content ';
$article->save();
echo $article->title . '|' . $article->content;
?>
Результат выполнения кода:
"My Article|Content"
Пример с использованием наблюдателя
Для организации кода лучше использовать наблюдатели. Рассмотрим пример наблюдателя для модели Article:
<?php
namespace App\Observers;
use App\Models\Article;
class ArticleObserver
{
public function saving(Article $article): void
{
if (empty($article->slug)) {
$article->slug = str($article->title)->slug();
}
if ($article->isDirty('status') && $article->status === 'published') {
$article->published_at = now();
}
}
}
?>
Регистрация наблюдателя в сервис-провайдере:
<?php
namespace App\Providers;
use App\Models\Article;
use App\Observers\ArticleObserver;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot(): void
{
Article::observe(ArticleObserver::class);
}
}
?>
Сохранение статьи с автоматической установкой 'slug' и 'published_at':
<?php
use App\Models\Article;
$article = new Article();
$article->title = 'New Article';
$article->status = 'published';
$article->save();
echo $article->slug . '|' . $article->published_at;
?>
Результат выполнения кода:
"new-article|2024-01-15 10:30:00"