これまで Laravel の Artisan コマンドを使ってできることを紹介しました。
前回の内容は、こちらをご覧ください。
▶︎PHP フレームワーク『 Laravel 』入門 #5 シーディング機能と Faker を使ってテストデータ作成
Artisan コマンドにはたくさんの機能が備わっていますが、その他にもオリジナルのコマンドを作成することができます。
今回はオリジナルの Artisan コマンドを作成する方法と、作成したコマンドを定期実行するための Laravel のコマンドスケジューラに登録する方法を紹介します。
この2つの機能を組み合わせると「毎日決められた時間にある処理を実行する」といったバッチ処理を簡単に実装することができます。
また、作成したオリジナルコマンドは他の Artisan コマンドと同様にコンソールからも簡単に実行できるので、自分が作ったプログラムを他の開発者に利用させる際にも便利です。
目次
- Artisan オリジナルコマンドの作成
1.1 コマンドクラスの生成
1.2 オリジナルコマンドの実装
1.3 コマンドの実行 - コマンドスケジューラにオリジナルコマンドを登録する
2.1 スケジュールの登録
2.2 コマンドスケジューラの有効化 - コマンドの実行結果をログファイルに出力する
- 最後に
「Webサイトからお問い合わせが来ない…」とお悩みの方必見!
当サイトのノウハウを詰め込んだ『Web集客の無料ガイド』をご提供
1. Artisan オリジナルコマンドの作成
Artisan のオリジナルコマンドを作成すれば、自分で実装した任意の処理をコンソールおよびコマンドスケジューラから実行することができます。
今回の記事では、データベース上の User テーブルに登録されているユーザーの件数を毎分取得するコマンドを作成してみます。
1.1 コマンドクラスの生成
まず、オリジナルコマンドの処理を記述するためのコマンドクラスを生成します。
コマンドクラスは Artisan make:command コマンドを実行することで、はじめから用意されている雛形を元に自動で生成することが可能です。
# Laravelプロジェクト(PROJECT_NAME)に移動 cd ~/html/laravel/PROJECT_NAME # オリジナルコマンド用のコマンドクラスを生成する php-7.1 artisan make:command UserCountCommand
今回は User テーブルに登録されているユーザーの件数を取得するためのコマンドのため、クラス名は UserCountCommand としています。
成功すると、コマンドクラスのファイルが app/Console/Commands/ の直下に作成されます。
1.2 オリジナルコマンドの実装
1.1で生成したコマンドクラスは何も処理が書かれていない空っぽの状態であるため、コマンドの名前と任意の処理を記入していきます。
管理ユーザー登録用の UserCountCommand ファイルをテキストエディタで開いて編集します。
app/Console/Commands/UserCountCommand.php
<?php namespace App\Console\Commands; use Illuminate\Console\Command; use App\User; class UserCountCommand extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'user:count'; /** * The console command description. * * @var string */ protected $description = 'Command description'; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return mixed */ public function handle() { //標準出力またはログに出力するメッセージ $message = '[' . date('Y-m-d h:i:s') . ']UserCount:' . User::count(); //INFOレベルでメッセージを出力する $this->info( $message ); } }
まず、Userテーブルに対して操作を行うので、
use App\User;
で User モデルを読み込んでいます。
次に
rotected $signature = 'user:count';
の部分ですが、変数 $signature にコマンドの名前を設定します。
コマンドの名前は任意ですが、覚えやすいものをつけましょう。
最後に、コマンドが実行されたときの処理を handle() メソッドの中に記入します。
データベース上にある User テーブルの情報を参照するのに、Laravel の Eloquent ORM という機能を使って User::count プロシージャを呼び出しています。
Eloquent ORM について今回は説明を省略しますが、SQL を書かずにテーブルの参照・登録・更新・削除ができるとても便利な機能です。
メッセージの出力は echo でもできますが、今回はコマンドクラスに用意された標準出力用のメソッド
$this->info()
を使用します。
コマンドクラスには $this->info() の他にも、エラー出力用の $this->error() や、配列を渡すことで自動的にテーブルレイアウトに整形してくれる $this->table () などの便利な標準出力用のメソッドが用意されています。
コマンドクラスの作成が終わったら、作成したコマンドクラスを Laravel に認識させるために下記コマンドを PROJECT_NAME 配下で実施し、オートロードの再構成を行います。
php-7.1 ../composer.phar dump-autoload
Laravel は必要なファイルを自動的に読み込む、Composer のオートロードという仕組みを利用しています。
Laravelで開発を進めていくと、新しいファイルを追加した時などさまざまな場面で「 Class <ファイル名> does not exist 」というエラーが発生することがあります。
上記のエラーが発生したら、まずオートロードの再構成を行ってみてください。
1.3 コマンドの実行
1.2で作成したオリジナルコマンドを、コンソールから実行してみます。
php-7.1 artisan user:count
実行結果は標準出力に出力されます。
成功したら、以下のようなメッセージが緑色の文字で表示されます。
2. コマンドスケジューラにオリジナルコマンドを登録する
Laravel にはコマンドスケジューラという機能があります。
コマンドスケジューラは、あるコマンドを定期実行(決められた日時に繰り返し実行)させるための機能です。
Linux サーバーを利用されている場合、サーバーの Cron を利用して定期実行を設定する方法がポピュラーですが、Laravel には Cron より便利なコマンドスケジューラの機能があるので、そちらを使用しましょう。
2.1 スケジュールの登録
まずコマンドスケジューラに、定期実行したいコマンドとそれを実行するスケジュールを登録します。
今回は、1.で作成したオリジナルコマンドを毎分ごとに実行するというスケジュールを追加してみます。
app/Console/Kernel.php
<?php namespace App\Console; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel { /** * The Artisan commands provided by your application. * * @var array */ protected $commands = [ \App\Console\Commands\UserCountCommand::class ]; /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { // user:countコマンドを毎分実行する $schedule->command('user:count')->everyMinute(); } /** * Register the commands for the application. * * @return void */ protected function commands() { $this->load(__DIR__.'/Commands'); require base_path('routes/console.php'); } }
追加するのは全部で2箇所です。
まず、配列 $commands に1.で作成したコマンドクラスの情報を指定します。
末尾をクラス名::class とするところに注意してください。
次に、schedule メソッドの中にコマンドを実行したいスケジュールを記入します。
$schedule->command('user:count') の部分でどのコマンドを実行するかを明示して、->everyMinute() の部分で実行する日時を指定しています。
everyMinute メソッドは毎分実行するという設定ですが、他にも Cron と同じような細かい実行タイミングの設定が可能です。代表的なものを以下に紹介します。
- 毎時間実行する
$schedule->hourly(); - 毎日12時00分に実行する
$schedule ->daily(); - 毎日指定した時間に実行する
$schedule ->dailyAt('5:15'); - 毎月指定した日時に実行する
$schedule ->monthlyOn(25, '23:55'); - Cronと同じ書き方で指定することもできます
$schedule ->cron('* * * * * *');
2.2 コマンドスケジューラの有効化
2.1でスケジュールの登録を行いましたが、これだけではまだコマンドスケジューラは有効になっていません。
Laravel のコマンドスケジューラは裏で Cron の機能を利用していますので、crontab に Artisan のコマンドスケジューラを有効にするための設定を追加する必要があります。
Laravel のコマンドスケジューラを有効化するためには、crontab に以下の設定を追加する必要があります。
* * * * * /usr/local/bin/php-7.1 /usr/home/<ユーザー名>/html/laravel/PROJECT_NAME/artisan schedule:run
共用レンタルサーバー『 ACE01 』では、直接Cronテーブルを編集することができませんので、下記手順に従い「スクリプト定期実行ツール」を利用します。
「スクリプト定期実行ツール」では定期実行のスケジュールを登録する際に、ファイルを指定する必要があります(実行するコマンドを直接書くことができません)。
そのために、まず Artisan のコマンドスケジューラを実行するためのコマンドを実行するための PHP ファイル (do_cron.php) を作成します。
do_cron.php
<?php exec('/usr/local/bin/php-7.1 /usr/home/<ユーザー名>/html/laravel/PROJECT_NAME/artisan schedule:run');
exec 関数は PHP からコマンドラインの外部コマンドを実行することができます。またこの際に、PHP と Artisan については絶対パスで指定するようにしてください。
ファイルを作成しましたら、サーバーのコントロールパネルにログインして、「スクリプト定期実行ツール」で先ほど作成したファイルを定期実行する設定を行います。
「公開サイト用設定」→「スクリプト定期実行ツール」を選択すると以下のような設定画面が表示されます。
写真を参考にして、次のように設定してください。
- 「新規登録」は先ほど作成したファイル (do_cron.php) を選択
- 「 PHP のバージョン」は7.1~を選択
- 「実行スケジュール」は1分毎になるように選択
全ての選択が終わったら「追加する」ボタンをクリックしてください。
これでコマンドスケジューラが有効になり、2.1で登録したスケジュールどおりにコマンドが定期実行されるようになりました。
3. コマンドの実行結果をログファイルに出力する
ここまでの手順を振り返ると、1.で作成したオリジナルコマンドを2.で定期実行するように設定しました。
しかし、今のままではコマンドスケジューラで定期実行されるコマンドはバックグラウンドで実行されているため、実行結果を知ることができません。
また、正常に完了したのか、エラーが発生したのかも分かりません。
これでは不便なため、コマンドの実行結果やエラーを記録するログファイルを作って、そのファイルに結果を出力するように設定してみましょう。
Laravel のコマンドスケジューラには、ログファイルを出力するためのメソッドも用意されています。
app/Console/Kernel.php
~省略~ protected function schedule(Schedule $schedule) { // user:countコマンドを毎分実行して、ログファイルに出力する $schedule->command('user:count')->everyMinute() ->appendOutputTo(storage_path('logs/user_count.log') ); } ~省略~
ログファイルを出力するには、appendOutputTo メソッドを使用します。
appendOutputTo メソッドはファイルが既に存在する場合は追記して、存在しない場合は新規作成を行います。
追記ではなく実行ごとに新しいログファイルを作成したい場合は appendOutputTo メソッドの代わりに sendOutputTo メソッドを使用してください。
storage/logs/ にログファイル user_count.log が作成されます。
毎分コマンドの実行結果が記述されていることを確認してください。
4. 最後に
今回の記事では、Artisan のオリジナルコマンド作成とコマンドスケジューラの設定方法について紹介しました。Web アプリケーションでは定期実行によるバッチ処理を実装することが多いので、Laravel のコマンドスケジューラを使いこなして、開発効率の向上を目指しましょう。
次回は、Laravel を使ったログイン機能の作成手順と、カスタマイズの方法について解説します。
▶︎PHP フレームワーク『 Laravel 』入門 #7 ログイン機能とカスタマイズ方法