Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама
Middle Eloquent

Як автоматично видаляти застарілі записи за допомогою Prunable і MassPrunable?

Багато таблиць ростуть безкінечно: журнали подій, прочитані сповіщення, прострочені токени, м'яко видалені записи. Laravel дає вбудований механізм їх періодично прибирати.

Prunable - описати, які записи застаріли:

use Illuminate\Database\Eloquent\Prunable;

class LoginAttempt extends Model
{
    use Prunable;

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

    protected function pruning(): void
    {
        // перед видаленням кожної моделі: прибрати пов'язані файли тощо
    }
}

Запуск за розкладом:

// routes/console.php
Schedule::command('model:prune')->daily();

Команда знаходить усі моделі з трейтами Prunable / MassPrunable у app/Models і видаляє записи, які повертає prunable().

php artisan model:prune --pretend    # скільки буде видалено, без видалення
php artisan model:prune --model="App\Models\LoginAttempt"

Prunable проти MassPrunable:

Prunable MassPrunable
як видаляє завантажує моделі порціями й викликає delete() для кожної один DELETE за запитом (порціями)
події deleting/deleted, спостерігачі так ні
хук pruning() так ні
швидкість на мільйонах рядків повільно швидко

М'яке видалення: якщо модель використовує SoftDeletes, Prunable видаляє записи остаточно (forceDelete). Типова схема - м'яко видалені записи старші за 30 днів прибирати назавжди.

Що важливо:

  • індекс на колонці умови (created_at) - інакше щоденне очищення читає всю таблицю;
  • перший запуск на таблиці з роками даних може видалити мільйони рядків і довго тримати блокування - краще спершу почистити вручну порціями, а потім ввімкнути розклад;
  • MassPrunable не викликає подій - пов'язані файли, кеш, пошуковий індекс не очищаються автоматично;
  • політика зберігання даних (скільки зберігати журнали, персональні дані) - це юридичне питання, а prunable() - місце, де вона виконується в коді;
  • тестування: у тесті можна створити старі й нові записи фабрикою, викликати $this->artisan('model:prune') і перевірити, що лишилися лише нові.

Докладніше в документації: Eloquent: очищення моделей

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання