Laravelで書いた処理をCronを使って自動実行させる

###はじめに

Laravelを使ってアプリを作成していると、処理を自動で実行させたいなと思うことが多々ありました。

調べてみるとLaravelでは、コントローラで書いた処理をcronを使って自動実行させることが可能だと知りました。

サイトなど参考しながら実際にやってみて、自動で動いてくれた時は感動しました。

今後も使っていこうと思い、Laravelのコントローラで書いた処理を自動実行させる手順をまとめました。

#####使用したバージョンなど
Laravel 5.8.35

#####前提条件と参考サイト
サーバ側の設定は利用するサーバ等によって異なるので、
ここではサーバ側の設定は終わっていてlaravel側での設定方法を書いております。

https://hiroslog.com/post/70

サーバ側の設定や手順の方法は、こちらの記事を参考にさせて頂きました。

### 自動実行させたい処理をコントローラに記述
まず、コントローラを作ります。

```ruby:command
php artisan make:controller AutoController
```

ここでは、AutoControllerとします。successfulyとメッセージが出れば成功です。
app/Http/ControllersにAutoControllerのファイルができているので開きます。

```ruby:app/Http/Controllers/AutoController
class AutoController extends Controller
{
    public function make_title()
    {
        // 実行させる内容
    }
}
```
コントローラ処理についてはcronだからと言って何か記述が必要というわけではありません。

普段通り書いちゃって大丈夫です。

書き終わったらcronを実行させるためのスケジューラを設定します。

スケジューラもコマンドで作成が可能です。

```ruby:command
 php artisan make:command AutoCommand
```

作成されると、app/Console/CommandsにAutoCommand.phpが作成されます。

```ruby:app/Console/Commands/AutoCommand.php
<?php
namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Http\Controllers\AutoController; //←追加

class AutoCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'command:make_title'; //←追加（コマンド名）

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'example make title'; //←追加（コマンド説明）

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        AutoController::make_title(); //←追加（先ほど書いたコントローラ）
    }
}
```

protected $signatureの部分には、

command:コマンド名

で名前をつけてあげます。自分が分かるものを書けば大丈夫です。


protected $description の部分には、コマンドの説明を記述します。

こちらも自由に記述すればOKです。

後ほど説明する時にここで書いたものが表示されている事で確認できますので、分かるように書いておくといいです。

記述が終わったら、最後にKernelで上記のスケジューラを動かすための記述します。

Kernelはlaravelのプロジェクト内に最初から用意されています。

```ruby: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 = [
        //追記（Commandsで記述したクラスを記述）
        \App\Console\Commands\AutoCommand::class,
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        // スケジュールをいつ実行させるのかを記述する

        $schedule
        ->command('command:make_title')
        ->withoutOverlapping()
        ->dailyAt('15:00');

        // withoutOverlappingをつけることで多重実行を防ぐので書いた方が無難
        // dailyAt('15:00')で毎日午後３時に実行

    }

    /**
     * Register the commands for the application.
     *
     * @return void
     */
    protected function commands()
    {
        $this->load(__DIR__.'/Commands');

        require base_path('routes/console.php');
    }
}
```
いつ処理を実行させるかの時間は、他にも書き方がたくさんあります。

公式ドキュメントには、繰り返しのスケジュールオプションに実行する時間についてまとめてあるので自分が実行させたい時間を調べて記述します。

https://readouble.com/laravel/5.8/ja/scheduling.html

ここまで書いて問題がなければ、コントローラで書いた内容が実行されるようになります。

###動かない時の対処法

設定してもCronが動かない時は、まずスケジューラがきちんと登録されているか確認します。

確認する方法は、プロジェクトのルートディレクトリで以下を実行させます。

```ruby:command
php artisan list
```

こちらを実行する事で、実行できるコマンドの一覧が表示されます。

先ほど作成したコマンドが、commandという場所に記載がされているか確認します。

```ruby:command
 cache
  cache:clear            Flush the application cache
  cache:forget           Remove an item from the cache
  cache:table            Create a migration for the cache database table
 command
  command:make_title     example make title

```
きちんと登録されている場合は、app/Console/Commands/AutoCommandで記述したコマンド名とコマンドの説明が記載されています。

記述したコマンド名とコマンド説明があれば、きちんとコマンドとして認識されているという事になります。

もしされていない場合は、コマンドの指定や記述が間違っている可能性があるので、作成したファイルが間違っていないが確認してみましょう。

####commandに記載がある場合

登録したものがある場合は、手で書いて実行してみます。

下記のようにコマンド名を書くと即実行させることができます！

```ruby:command
php artisan command:make_title 
```

これでエラーが出れば、コントローラ内の処理で何らかのエラーが表示されます。

原因はコントローラ自体の処理に問題があることが分かるので、適宜エラー文をみて修正します。


成功した場合は特に何も表示されません。

コントローラに記述した処理がされているか確認しましょう。

自分が開発時にcronが動かない時は、これでエラーの内容を確認することができました。

原因を突き止めるきっかけになりますので、参考になれば幸いです。