Laravel: Soft delete. Полное руководство

Источник: «Laravel soft delete: the definitive guide for 2022»
Soft delete в Laravel позволяет предотвратить ошибки, не удаляя конфиденциальные данные из базы данных сразу.

Что такое soft delete?

Soft delete или мягкое удаление — пометка модели как удалённой без фактического удаления её из базы данных.

Представьте в вашей базе данных поле deleted_at, содержащий дату, когда запись была удалена.

В чём преимущество soft delete?

Основное преимущество soft delete в том, что вы не теряете данные. Вы всегда сможете их восстановить.

Так же можно настроить запланированную задачу для очистки старых мягко удалённых моделей, если прошло достаточно времени с момента удаления. (Как только они будут удалены, вы сможете восстановить их только из своей резервной копии.)

Как настроить soft delete?

Laravel требует, чтобы вы сделали два простых шага для настройки soft delete.

Во-первых, укажите, что вам нужно поле таблицы для soft delete в вашем файле миграции. Как только вы запустите его, вы увидите новое поле deleted_at в своей таблице.

public function up()
{
Schema::table('posts', function (Blueprint $table) {
+ $table->softDeletes();
});
}

В методе down() вы можете удалить это поле с помощью метода dropSoftDeleted().

public function down()
{
Schema::table('posts', function (Blueprint $table) {
+ $table->dropSoftDeletes();
});
}

Затем импортируйте в вашей модели трейт SoftDeletes.

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class Post extends Model
{
+ use HasFactory, SoftDeletes;
}

Как выполнить soft delete?

Для мягкого удаления в Laravel вам не нужно менять свои привычки. Используйте метод delete() вашей модели, как и раньше. Единственная разница будет заключаться в том, что Laravel добавит текущую дату и время в поле deleted_at.

$post->delete();

Как проверить, была ли модель мягко удалена?

Для проверки, была ли модель мягко удалена используйте метод trashed().

if ($post->trashed()) {
//
}

Хэлперы для soft delete

Иногда может потребоваться получить мягко удалённые модели в запросе. В этом может помочь диапазон (scope) withTrashed().

Post::withTrashed()->get();

Вы можете запрашивать только обратимо мягко модели:

Post::onlyTrashed()->get();

Кроме того, поскольку модель на самом деле никогда не удалялась, вы можете восстановить её с помощью метода restore(). Значение в поле deleted_at снова станет NULL.

$post->restore();

Наконец, если вы действительно хотите удалить мягко удаляемую модель из базы, используйте метод forceDelete().

$post->forceDelete();

Как протестировать soft delete?

Для теста soft delete в Laravel, используется метод assertSoftDeleted().

Вот базовый пример того, как я бы это сделал:

public function test_it_soft_deletes_posts()
{
$post = Post::factory()->create();

$this
->deleteJson(route('posts.destroy', $post))
->assertNoContent();

$this->assertSoftDeleted($post);
}

Существует и обратный метод assertNotSoftDeleted().

Как очистить старые мягко удалённые модели?

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

Например, импортируйте трейт Prunable в модель и скажите фреймворку удалить модели, которые были мягко удалены месяц назад или более.

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Prunable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class Post extends Model
{
use HasFactory, Prunable, SoftDeletes;

public function prunable()
{
return static::where('deleted_at', '<=', now()->subMonth());
}
}

Не забудьте добавить команду model:prune в планировщик. Добавьте её в app/Console/Kernel.php:

protected function schedule(Schedule $schedule)
{
+ $schedule->command('model:prune')->daily();
}

На этом всё. Подробнее о планировщике вы можете узнать из статьи Laravel: Как работает cron и планировщик задач

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

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

Laravel 10: Дата выхода и новые возможности

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

Laravel: Все секреты миграции