Планирование периодической очистки базы данных на 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 для выполнения любого желаемого действия перед удалением.