В 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.
