Laravel Artisan コマンド:model:prune
要点(TL;DR)
| 何をするか |
実行例 |
重要なオプション |
| 定義済み Prunable ロジックを実行し、不要レコードを削除 |
php artisan model:prune |
--force, --dry-run, --model |
警告
本番環境で --force を付けずに実行すると、確認プロンプトで停止します。
--dry-run は削除件数のみ表示し、実際にレコードは削除されません。
1. 概要
model:prune は Laravel 9 で導入された Artisan コマンドで、Eloquent モデルに public function prunable(): Builder を実装した「削除対象」を自動でクリーンアップします。
コマンド実行時に各モデルの prunable() を呼び出し、返却されたクエリビルダーで取得したレコードを delete() で一括削除します。
2. コマンドシグネチャ
php artisan model:prune [options] [--model=]...
| オプション |
型 |
必須 |
既定値 |
説明 |
--force |
bool |
いいえ |
false |
確認プロンプトをスキップ |
--dry-run |
bool |
いいえ |
false |
削除件数を表示のみ(実際は削除しない) |
--model |
string[] |
いいえ |
[] |
指定モデルのみを対象(複数可) |
--except |
string[] |
いいえ |
[] |
指定モデルを除外 |
戻り値
int – 削除件数(--dry-run でも削除件数を返す)。
3. 実務での使い方
3.1 典型的なユースケース
例:30日以上非アクティブなユーザーを削除
// app/Models/User.php
use Illuminate\Database\Eloquent\Prunable;
use Illuminate\Support\Carbon;
class User extends Model
{
use Prunable;
public function prunable()
{
return static::where('last_login_at', '<', Carbon::now()->subDays(30));
}
}
# まず削除件数を確認
php artisan model:prune --dry-run
# => 200 件が削除対象です
# 本番で削除
php artisan model:prune --force
# => 200 件が削除されました
3.2 モデル限定で実行
php artisan model:prune --model=User --model=Post
3.3 除外モデルを指定
php artisan model:prune --except=ArchivedUser
4. 代替手段との比較
| 手段 |
メリット |
デメリット |
Model::query()->where(...)->delete() |
条件自由度が高い |
逐次削除で遅い |
php artisan db:wipe |
テーブル全体をリセット |
すべてのデータが消える |
model:prune |
一括安全削除、トランザクション内 |
prunable() の実装が必要 |
5. よくある落とし穴
| 症状 |
原因 |
対処 |
| コマンドが停止 |
本番環境で --force を付け忘れ |
--force を追加 |
| 削除件数がゼロ |
prunable() の条件ミス |
条件を確認し --dry-run で検証 |
| 大量削除時にタイムアウト |
一度に大量レコードを削除 |
--model で対象を限定、またはバッチ処理を自前実装 |
| 削除が意図しないテーブルへ影響 |
prunable() に結合クエリを含めた |
参照整合性を確認、必要なら onDelete('cascade') を設定 |
6. テスト例(Pest)
it('prunes old users', function () {
User::factory()->create(['last_login_at' => now()->subDays(40)]);
User::factory()->create(['last_login_at' => now()]);
$this->artisan('model:prune')
->expectsOutput('1 record(s) deleted.')
->assertExitCode(0);
expect(User::count())->toBe(1);
});
7. 参考リンク