В Laravel 8.50 появилась новая функция Models Pruning (Очистка моделей). С помощью неё можно автоматически зачищать модели от старых записей.
Предположим, что у нас есть чат и нам нужно удалять все сообщения старше одной недели. Добавляем в модель трейт Illuminate\Database\Eloquent\Prunable
и реализуем метод prunable
, который должен вернуть конструктор запросов с условиями очищения.
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Prunable; class Message extends Model { use Prunable; public function prunable() { return static::where('created_at', '<=', now()->subDays(7)); } }
Также можно реализовать метод pruning
, который выполнится перед очисткой экземпляра модели. Например мы можем удалить приаттаченные к сообщению файлы.
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Prunable; class Message extends Model { use Prunable; public function attachment() { return $this->hasOne(Attachment::class); } public function prunable() { return static::where('created_at', '<=', now()->subDays(7)); } protected function pruning() { return $this->attachment->delete(); } }
Чтобы всё это заработало нужно запланировать выполнение команды model:prune
в App\Console\Kernel
с определенным интервалом. Зададим ежедневную очистку:
/** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { $schedule->command('model:prune')->daily(); }
Если необходимо задать разный интервал для разных моделей, то используйте опцию --model
. Сами классы можно перечислять через запятую:
$schedule->command('model:prune', [ '--model' => [Message::class, Attachment::class], ])->daily();
Также есть трейт Illuminate\Database\Eloquent\MassPrunable
. Он позволяет очищать модели с помощью запросов массового удаления, в отличии от первого трейта, который удаляет по одному экземпляру. Обратите внимание, что в таком случае не будет вызываться метод pruning
и не будут отправляться события deleting
и deleted
, так как, в целях быстродействия, модели не извлекаются перед удалением.
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\MassPrunable; class Message extends Model { use MassPrunable; public function prunable() { return static::where('created_at', '<=', now()->subDays(7)); } }
Автор: Алексей Широков
Наш Телеграм-канал — следите за новостями о Laravel.