Laravelのタスクスケジューラを使う

# 目次
Laravelの記事一覧は下記
[PHPフレームワークLaravelの使い方](https://qiita.com/toontoon/items/c4d0371e504c37f6576e)

# Laravelバージョン
動作確認はLaravel Framework 7.19.1で行っています

# 前提条件
[eclipseでLaravel開発環境を構築する。デバッグでブレークポイントをつけて止める。(WindowsもVagrantもdockerも)](https://qiita.com/toontoon/items/76fa7f8845b20776077c)
本記事は上記が完了している前提で書かれています
プロジェクトの作成もapacheの設定も上記で行っています

[Laravelでコマンドライン処理を行う](https://qiita.com/toontoon/items/2015ec0deea4b11e5361)
本記事は上記の内容を理解している前提で書かれています

# Commandクラス作成
コマンドラインで
`cd sample`
`php artisan make:command SampleSchedule`
xdebugの設定をしているとeclipseが実行していいですかというプロンプトを出すのでOKを押します
eclipseプロジェクトを右クリック→リフレッシュ
/sample/app/Console/Commands/SampleSchedule.phpが現れます

# Commandクラス修正
さきほど作成したSampleSchedule.phpを下記に修正します

```SampleSchedule.php
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class SampleSchedule extends Command
{
    protected $signature = 'sample:name2 {arg1}';

    protected $description = 'SampleSchedule';

    public function __construct()
    {
        parent::__construct();
    }

    public function handle()
    {
        $arg1 = $this->argument('arg1');
        $this->line('arg1:' . $arg1);
        if ($arg1 === 'a') {
            return 1;
        }
        return 0;
    }
}

```

# Commandクラス登録
/sample/app/Console/Kernel.php修正

```Kernel.php
‥‥
    protected $commands = [
　　　　　‥‥
        ,Commands\SampleSchedule::class
    ];

‥‥
```

Kernel.phpに定義されている$commands配列に先ほど作成したSampleScheduleクラス名を追記します

# スケジュール作成
(1) /sample/app/Console/Kernel.phpに下記use文を追記
`use Illuminate\Support\Facades\Log;`

(2) /sample/app/Console/Kernel.phpのscheduleメソッドを修正します

```Kernel.php

    protected function schedule(Schedule $schedule)
    {
        $schedule->command('sample:name2 0')
                 ->everyMinute()
                 ->appendOutputTo(dirname(dirname(dirname(__FILE__))) . '/storage/logs/SampleSchedule.log')
                 ->onSuccess(function () {
                     Log::info('成功');
                 })
                 ->onFailure(function () {
                     Log::error('エラー');
                 })
                 ;

        $schedule->command('sample:name2 a')
                 ->everyMinute()
                 ->appendOutputTo(dirname(dirname(dirname(__FILE__))) . '/storage/logs/SampleSchedule.log')
                 ->onSuccess(function () {
                     Log::info('成功');
                 })
                 ->onFailure(function () {
                     Log::error('エラー');
                 });

        $schedule->command('sample:name2 z')
                 ->dailyAt('10:00')
                 ->appendOutputTo(dirname(dirname(dirname(__FILE__))) . '/storage/logs/SampleSchedule.log')
                 ->onSuccess(function () {
                     Log::info('成功');
                 })
                 ->onFailure(function () {
                     Log::error('エラー');
                 })
                 ;

    }

```
command関数は実行するコマンドクラスを指定します。引数はCommandクラスのsignature変数に定義した通りに書きます。php artisanコマンドでCommandクラスを実行するときと同じものになります[[Laravelでコマンドライン処理を行う](https://qiita.com/toontoon/items/2015ec0deea4b11e5361)]。
everyMinute関数は毎分実行する指定になります
appendOutputTo関数はCommandクラスからの出力先を指定したファイルにするものです
onSuccess関数はCommandクラスから戻り値が0の場合に実行される処理を指定します。ただし、動作確認したLaravelバージョン7.1.1ではCommandクラスをバックグラウンド実行すると戻り値が0でもonSuccessが実行されないです。バックグラウンド実行はメソッドチェーンで[runInBackground](https://readouble.com/laravel/7.x/ja/scheduling.html#background-tasks)関数を指定するとできるようになります。
onFailure関数はCommandクラスから戻り値が1の場合に実行される処理を指定します。ただし、動作確認したLaravelバージョン7.1.1ではCommandクラスをバックグラウンド実行すると戻り値が何であってもonFailureが実行されます。バックグラウンド実行はメソッドチェーンで[runInBackground](https://readouble.com/laravel/7.x/ja/scheduling.html#background-tasks)関数を指定するとできるようになります。
dailyAt関数は毎日決まった時間にCommandクラスを実行する指定になります
everyMinute関数やdailyAt関数といった実行日時を指定する関数はいろいろ用意されています。下記で確認できます
[Laravel 7.x タスクスケジュール 繰り返しのスケジュールオプション
](https://readouble.com/laravel/7.x/ja/scheduling.html#schedule-frequency-options)

# 動作確認
コマンドラインで
`cd sample`
`php artisan schedule:run`
xdebugの設定をしているとeclipseが実行していいですかというプロンプトを出すのでOKを押します

/sample/storage/logs/SampleSchedule.logにSampleSchedule.phpからの出力が書き込まれています
/sample/storage/logs/laravel.logに/sample/app/Console/Kernel.phpのscheduleメソッド内にonSuccess、onFailureで指定したクロージャからの出力が書き込まれています

また、`php artisan schedule:run`を実行したウインドウを見ると
php "artisan" sample:name2 0
php "artisan" sample:name2 a
が実行されたことがわかります
さらに、実行した時刻が10:00の場合、php "artisan" sample:name2 zも実行されているでしょう

# cron登録とスケジューラとしての使い方
先ほどコマンドラインで/sample/app/Console/Kernel.phpのscheduleメソッドを実行してみました
これをcronに指定します
`* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1`
/path-to-your-projectというのはご自身のLaravelプロジェクトへの絶対パスに書き換えてください
この記事であればsampleフォルダになります
このcronの設定を見ると分、時、日、月、曜すべてアスタリスクになっていることがわかります
これは1分に1回、要は毎分php artisan schedule:run実行されるという設定になります
つまり、毎分`php artisan schedule:run`が実行されて、その際、実行日時に合う[タスクスケジュール繰り返しのスケジュールオプション](https://readouble.com/laravel/7.x/ja/scheduling.html#schedule-frequency-options)が設定されているcommandだけが実行されるという仕組みです

先ほどコマンドラインで`php artisan schedule:run`を実行した際、everyMinute指定したものが実行されて(ちょうど10:00に実行しなければ)dailyAt指定したものは実行されなかったと思います
これはphp artisan schedule:runが毎分実行されるようにつくられているからです