Soft delete моделей в Laravel: подробное руководство

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

Оглавление

Что такое soft delete

Soft delete позволяет разработчикам помечать модели как удалённые, не удаляя их из базы данных.

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

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

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

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

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

Сначала укажите, что вам нужен столбец для мягкого удаления в миграции (я написал статью о миграциях Laravel: Все секреты миграции). После выполнения миграции вы увидите новый столбец deleted_at в таблице posts.

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

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

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 и проверить его

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

$post->delete();

А если вы хотите проверить, была ли модель soft delete, я рекомендую использовать метод trashed(), а не проверять вручную столбец deleted_at.

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

Дополнительные хелперы для soft delete

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

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

Вы даже можете запрашивать только soft delete модели:

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

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

$post->restore();

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

$post->forceDelete();

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

Чтобы протестировать Soft delete в Laravel, используйте метод assertSoftDeleted(), предоставляемый Laravel.

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

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

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

$this->assertSoftDeleted($post);
}

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

Как очистить старые soft delete модели

Вы можете использовать механизм очистки, предлагаемый Laravel, для очистки старых soft delete моделей.

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

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: Все секреты миграции