📄
Laravel で簡易スクリプトを実行する仕組みを作る
はじめに
Laravel を使用しているプロジェクトで、1年に一度、データベースに年次データを追加してほしいという依頼が来ていました。
従来は SQL で追加していましたが、何点か問題や改善したい点がありました。
- 実行した履歴を残したい
- Eloquent や PHP の機能を使いたい
- 一度実行したら再度実行できないようにしたい
- 特定のサーバの特定のユーザでしか実行できないようにしたい
これを解決するために、Artisan コンソールの機能を拡張してスクリプトを実行できる仕組みを作成しました。
環境
- PHP 8.0.x
- Laravel 8.x
作業工程
実行履歴を残すテーブルを作成
scripts
テーブルを作成します。
このテーブルで実行履歴を管理します。
イメージとしては migrations
テーブルと似たような感じです。
Scripts
フォルダを作成し、Artisan コマンドの配置場所として登録
class Kernel extends ConsoleKernel
{
/**
* Register the commands for the application.
*/
protected function commands()
{
$this->load([
__DIR__ . '/Commands',
__DIR__ . '/Scripts', // ここに追加
]);
require base_path('routes/console.php');
}
}
継承元となる抽象クラスを作成
Artisanコンソールで実行される handle()
をオーバーライドし、実行前と実行後の処理をフックできるようにしました。
実行前の処理では以下の機能を実現しています。
- 一度実行したら再度実行できないようにしたい
- 特定のサーバの特定のユーザでしか実行できないようにしたい
実行後には scripts
テーブルに実行記録を残しています。
スクリプトファイルを作成
後は Script
抽象クラスを継承して、スクリプトファイルを作成していきます。
<?php
namespace App\Console\Scripts;
class SampleScript20211014 extends Script
{
/**
* The name and signature of the console command.
*/
protected string $signature = 'scripts:sample-script-20211014';
/**
* The console command description.
*/
protected string $description = 'サンプルスクリプト';
protected function script()
{
\DB::beginTransaction();
// いろいろな処理
\DB::commit();
$this->info('Finish.');
}
}
テストを作成
抽象クラスである Script.php
のテストです。
getMockForAbstractClass()
を使ってモックしています。
さいごに
tinker
の代わりとして使え、実行ファイルも残るので改善ができたと思います。
ただヒューマンエラーは防げないので、乱用しないこと、コードをレビューしてもらうこと、データの追加や変更は必ずバックアップを取ったのち行うことも引き続き大事です。
ご安全に!
Discussion