Laravelでcron実行、名言をメール送信

Laravelでcron実行し、Laravelのコマンド Inspiring という、ランダムに名言を出力してくれる機能を使ってメール送信するメモ。

# 環境
- Laravel 10.4.1
- さくらVPSサーバー CentOS7
- PHP 8.2.4 

# 前提
Laravelでのメール送信設定ができていること

# Commandの作成
今回はSendInspiringというコマンドを作成。
```bash
php artisan make:command SendInspiring
```
\Laravelapp\app\Console\Commands\SendInspiring.php
が作成される。このファイルにコマンドの実行内容を追記する。

```PHP
namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Foundation\Inspiring;

class SendInspiring extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    // protected $signature = 'command:name';
    protected $signature = 'SendInspiring';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Send Inspiring message via email';

    /**
     * Execute the console command.
     */
    public function handle(): void
    {
        // 偉人の名言を出力する
        // strip_tags: 文字列から HTML および PHP タグを取り除く
        echo strip_tags(Inspiring::quote()). "\n";
        return;

    }
}
```
$signatureにコマンドの名前を登録。コマンドを実行する際に利用する。
```PHP
protected $signature = 'SendInspiring';
```
$descriptionにはコマンドの説明を記載。
```PHP
protected $description = 'Send Inspiring message via email';
```
handle()には実行する処理内容を記述。
```PHP
public function handle(): void
{
    // 偉人の名言を出力する
    // strip_tags: 文字列から HTML および PHP タグを取り除く
    echo strip_tags(Inspiring::quote()). "\n";
    return;

}
```
上部で、
use Illuminate\Foundation\Inspiring;
して
Inspiring::quote()
で名言が出力されるという仕組みです。

ちなみに、Laravel10以前では（？）\Laravelapp\app\Console\Kernel.php
に手動で追記してコマンドの登録が必要でしたが、Laravel10では、Kernel.phpの中身が、commandsフォルダ以下にあるファイルを自動的に読みに行くようになっており、登録は不要でした。
（コマンドファイルは、commandsフォルダ以下に自動で作成され、それが自動でロードされる）
```PHP:Kernel.php
protected function commands(): void
{
    $this->load(__DIR__.'/Commands');
    require base_path('routes/console.php');
}
```



# Commandの登録確認（呼び出して使えるか）
php artisan listコマンドの実行で、下記のように先ほどSendInspiring.phpで登録した「SendInspiring」コマンドが出てくるか確認。
確認できました。
```bash
> php artisan list
・・・（略）
Available commands:
  SendInspiring           Send Inspiring message via email
  about                   Display basic information about your 
  clear-compiled          Remove the compiled class file
・・・（略）
```

# 登録したCommandの実行
コマンドの登録が確認できたので、php artisan を使って実行させてみる。ランダムに出力される名言をechoで出力しているので、ここではbashに名言が出力されます。繰り返すと別の名言が出てきます。
```bash
# php artisan SendInspiring

  “ Very little is needed to make a happy life. ”
  ― Marcus Aurelius
```
```bash
# php artisan SendInspiring

  “ Because you are alive, everything is possible. ”
  ― Thich Nhat Hanh
```

# サーバーにCronへの登録
laravelのタスクスケジュールを設定するために、サーバーでcronに下記の1行を追加。`crontab -e`コマンドで。
※path-to-your-projectはLaravelをインストールしたフォルダを指定。各自の環境により異なる。

```bash
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
```
cron設定がすべて*(アスタリスク)になっているので、毎分`php artisan schedule:run`が実行される。
なお、laravelでのコマンド実行は、Laravelで実際にKernel.phpファイルにスケジュールされた頻度になる。
→Kernel.php に`->daily()`を指定すると、毎日0時実行、
　　　　　 　`->dailyAt('07:00')`だと、毎日AM7時になる。

# Laravelのタスクスケジュールへの登録
コマンドの単独での動作確認ができたので、定期的に実行されるように、Kernel.phpファイルのschedule()に登録を行います。

```PHP
    protected function schedule(Schedule $schedule): void
    {
        //名言を朝7時に送信
        $today_tmp = date("Y/m/d") ;
        $schedule->command('SendInspiring')
                    ->everyMinute()   //テスト用
                    //->dailyAt('07:00')
                    ->name($today_tmp . " - today's Inspiring")    //emailのタイトルになる
                    ->sendOutputTo(storage_path('logs/Inspiring.log'))
                    ->emailOutputTo(\App\Consts\CommonConst::EMAIL_SendInspiring);
    }
```
まずは、頻度を`->everyMinute()`にし、実際にcronでメールが送信されるかを確認します。 
（Laravelでのメール送信設定は既にできていて、メール送信ができることを前提とします）
ここでは、コマンドを実行すると、
`/laravelapp/storage/logs/Inspiring.log`
が作成され、同じ内容がemailで届く、という流れになります。
`\App\Consts\CommonConst::EMAIL_SendInspiring`
は自分で指定した定数で、送信先メールアドレスになります。
（'****@gmail.com' のような直書きでも動作します）

- 動作確認成功。毎分1回、スケジュールで送信されたメールの例
```e-mail
subject：2023/04/18 - today's Inspiring
to:		****@gmail.com
from:	Laravel APP <****@gmail.com>
本文：

  “ Order your soul. Reduce your wants. ”
  — Augustine
```
toの送信先、subjectはKernel.phpで指定したもの、
from部分は、Laravelの環境設定（.envファイル）の
`MAIL_FROM_ADDRESS=`
`MAIL_FROM_NAME=`
で指定したものになります。


ここで、Kernel.phpの記載を、
```diff_PHP:Kernel.php
- ->everyMinute()   //テスト用
+ ->dailyAt('07:00')
```
のように変えると、毎日AM7時にメールが送信されることを確認できました。

# 関連記事
PHP（Laravel）からMicrosoft Translator APIを使って自動翻訳
https://qiita.com/ky-jp16/items/b8f5ae3f6544022f12e2
→この記事での機能に、翻訳した英文も送信する機能を追加した。

# 参考
[Laravelのタスクスケジュール(cron)を使いこなす](https://reffect.co.jp/laravel/laravel-task-schedule-cron)
[タスクスケジュール 10.x Laravel](https://readouble.com/laravel/10.x/ja/scheduling.html)

# 補足
名言の実体は、
`/laravelapp/vendor/laravel/framework/src/Illuminate/Foundation/Inspiring.php`
にあって（このバージョンでは）39の名言が登録されているのですが、このファイルのクラス定義の上部には、コメントで、翼があり炎を吐く龍？らしき動物が描かれています。遊び心？
```PHP:Inspiring.php
namespace Illuminate\Foundation;
use Illuminate\Support\Collection;
/*
                                                   .~))>>
                                                  .~)>>
                                                .~))))>>>
                                              .~))>>             ___
                                            .~))>>)))>>      .-~))>>
                                          .~)))))>>       .-~))>>)>
                                        .~)))>>))))>>  .-~)>>)>
                    )                 .~))>>))))>>  .-~)))))>>)>
                 ( )@@*)             //)>))))))  .-~))))>>)>
               ).@(@@               //))>>))) .-~))>>)))))>>)>
             (( @.@).              //))))) .-~)>>)))))>>)>
           ))  )@@*.@@ )          //)>))) //))))))>>))))>>)>
        ((  ((@@@.@@             |/))))) //)))))>>)))>>)>
       )) @@*. )@@ )   (\_(\-\b  |))>)) //)))>>)))))))>>)>
     (( @@@(.@(@ .    _/`-`  ~|b |>))) //)>>)))))))>>)>
      )* @@@ )@*     (@)  (@) /\b|))) //))))))>>))))>>
    (( @. )@( @ .   _/  /    /  \b)) //))>>)))))>>>_._
     )@@ (@@*)@@.  (6///6)- / ^  \b)//))))))>>)))>>   ~~-.
  ( @jgs@@. @@@.*@_ VvvvvV//  ^  \b/)>>))))>>      _.     `bb
   ((@@ @@@*.(@@ . - | o |' \ (  ^   \b)))>>        .'       b`,
    ((@@).*@@ )@ )   \^^^/  ((   ^  ~)_        \  /           b `,
      (@@. (@@ ).     `-'   (((   ^    `\ \ \ \ \|             b  `.
        (*.@*              / ((((        \| | |  \       .       b `.
                          / / (((((  \    \ /  _.-~\     Y,      b  ;
                         / / / (((((( \    \.-~   _.`" _.-~`,    b  ;
                        /   /   `(((((()    )    (((((~      `,  b  ;
                      _/  _/      `"""/   /'                  ; b   ;
                  _.-~_.-~           /  /'                _.'~bb _.'
                ((((~~              / /'              _.'~bb.--~
                                   ((((          __.-~bb.-~
                                               .'  b .~~
                                               :bb ,'
                                               ~~~~
 */
```

# 補足2
ちなみに、別の環境にLaravel 10.6.2を入れたところ、`php artisan`コマンドで確認して、下記の1行が出てこないので、この機能は削除された模様、、
```bash
 inspire                 Display an inspiring quote
```