Планирование периодической очистки базы данных на Laravel

Источник: «Schedule periodic database clean-up on Laravel»
Как очистить базу данных удалив ненужные данные с помощью встроенной функции Laravel для повышения производительности запросов

По понятным причинам таблицы баз данных со временем имеют тенденцию к увеличению размеров. Поэтому для поддержания производительности запросов время от времени требуется их настройка.

Среди распространённых методов — создание индексов, переписывание запросов и даже перепроектирование базы данных.

Но есть и другое очевидное решение, которое также может быть применено, — это очистка данных.

В Laravel для этого есть встроенная функция, которая может быть использована двумя различными способами: Очистка и Массовая очистка:

Очистка

Допустим, вы хотите удалить soft-deleted пользователей по истечении 90 дней с даты удаления.

Добавьте в модель трейт Illuminate\Database\Eloquent\Prunable и реализуйте метод prunable, возвращающий построитель запросов Eloquent, масштабирующий запрос для получения Prunable записей.

app/Models/User.php:

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Prunable;
use Illuminate\Database\Eloquent\SoftDeletes;

class User extends Model
{
use Prunable;
use SoftDeletes;

/**
* Get the prunable model query.
*/

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

Пометив модели как Prunable, можно также определить для них метод удаления. Этот метод будет вызываться перед удалением модели.

Чтобы показать реальное применение этого метода, предположим, что у пользователя есть фотография профиля, и её также необходимо удалить из файлового хранилища:

app/Models/User.php:

/**
* Prepare the model for pruning.
*/

protected function pruning(): void
{
Storage::delete($this->picture);
}

Теперь вы можете запустить команду artisan model:prune или запланировать её в классе App\Console\Kernel вашего приложения.

Вы можете задать желаемый интервал, но в данном случае мы хотим осуществлять очистку данных ежедневно:

app/Console/Kernel.php:

/**
* Define the application's command schedule.
*/

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

Когда вы выполняете команду model:prune, она обнаруживает модели в app/Models вашего приложения, в которых реализуется трейт Illuminate\Database\Eloquent\Prunable.

В случае если модели находятся в другом месте, можно использовать опцию --model:

app/Console/Kernel.php:

use App\Module\Models\User;

$schedule->command('model:prune', [
'--model' => [User::class],
])->daily();

С помощью опции --except можно также исключить Prunable модель, которая будет автоматически обнаружена в каталоге app/Models:

app/Console/Kernel.php:

$schedule->command('model:prune', [
'--except' => [AnotherModel::class],
])->daily();

Иногда перед удалением необходимо узнать, сколько записей будет удалено. Это называется пробным запуском, который можно выполнить с помощью опции --pretend.

php artisan model:prune --pretend

Массовая очистка

При очистке записи извлекаются и обходятся как объект eloquent, удаляя их по отдельности, что вызывает события модели.

При массовой очистке выполняется один запрос, не вызывается метод pruning, и события модели deleting и deleted.

app/Models/User.php:

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\MassPrunable;
use Illuminate\Database\Eloquent\SoftDeletes;

class User extends Model
{
use MassPrunable;
use SoftDeletes;

/**
* Get the prunable model query.
*/

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

Заключение

В этой статье вы узнали, как можно удалить ненужные данные с помощью встроенной функции Laravel и что можно удалить все сразу с помощью свойства Illuminate\Database\Eloquent\MassPrunable или запись за записью с помощью свойства Illuminate\Database\Eloquent\Prunable, которое позволяет определить метод pruning для выполнения любого желаемого действия перед удалением.

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

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

PHP 8.3: class_alias() создание псевдонимов встроенных классов

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

PHP 8.3: Вопросы безопасности при разборе пользовательских INI-строк и файлов