Implist | 個人プロダクト開発を加速させるための理論と実装

Laravel 9.x で「sitemap.xml」をcronを使って定期的に自動生成する


Laravel 9.x でサイトマップを作成する方法を紹介します。また自動的に生成されるような設定も行っていきます。

手順

  1. サイトマップ生成ライブラリのインストールと設定
  2. サイトマップ生成コマンド作成・登録
  3. 自動的に生成するようにコマンドを登録

このように、3ステップで簡単にsitemap.xmlが自動生成できます。では見ていきましょう。

以下を前提して話します。

  • Laravel 9.x
  • PHP 8.1
  • composer 2.3.5
  • 定期実行はcronを使用する 
     

サイトマップ生成ライブラリのインストールと設定

spatie/laravel-sitemap というサイトマップ生成ライブラリをインストールします。基本的にはこのライブラリのREADMEに記述されている内容になりますので、不明点ある場合はそちらを参考にしてください。

composer require spatie/laravel-sitemap 

インストールが完了したら、以下コマンドでsitemapの設定ファイル作成します。

php artisan vendor:publish --provider="Spatie\Sitemap\SitemapServiceProvider" --tag=sitemap-config

上記が成功すると、config/sitemap.php というファイルが作成されます。この内部は特に編集する必要はありません。

このライブラリはguzzleというライブラリが内部で使用され、httpリクエストを自身のサイトに対して行うことでサイトマップを生成していきます。割と原始的ですね。

サイトマップ生成コマンド作成・登録

インストールと設定が完了したので、次はサイトマップを生成するコマンドを作成します。

作成

今から作るコマンドを実行することで先ほどのライブラリが動いて、sitemap.xmlを生成してくれます。

以下ファイルを作成してください。

app/Console/GenerateSitemap.php
<?php
namespace App\Console;

use Illuminate\Console\Command;
use Spatie\Sitemap\SitemapGenerator;

class GenerateSitemap extends Command
{
protected $signature = 'sitemap:generate';
protected $description = 'サイトマップの生成を行う';

public function handle()
{
SitemapGenerator::create(config('app.url'))
->writeToFile(public_path('sitemap.xml'));
}
}

簡単に説明すると、$signatureがコマンドになって、handle()が実際のsitemap生成処理です。
sitemap:generateというコマンドを実行するとapp.urlに設定されているURLにアクセスして、publicディレクトリにsitemap.xmlというファイルを生成するという意味ですね。

登録

実はまだこのままだと、コマンドがLaravelから認識されていません。コマンド登録を行う必要があります。
とは言っても簡単で、Kernel.phpにの「追記」の行を足してください。

app/Console/Kernel.php
<?php

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
protected $commands = [
GenerateSitemap::class // 追記
];

protected function schedule(Schedule $schedule)
{
}

protected function commands()
{
$this->load(__DIR__.'/Commands');

require base_path('routes/console.php');
}
}

こうすることで、php artisanで実行できるようになります。

試しに実行してみる

以下コマンドを実行してみると、

php artisan sitemap:generate

public/sitemap.xmlが生成されます。

このようにsitemapが記述されているのが分かると思います。生成するときは単純なhttpリクエストによって解析されるので、非公開のルーティングや認証ありのページはここに載りません。

また、これはlocal環境(localの.env)で実行したのでlocalhostとなっています。
sitemap.xmlは通常Laravelが稼働しているサーバー上で生成することになると思うので、.gitignoreにsitemap.xmlを追加しておくことを推奨します。gitで管理下としても意味がないので。

自動的に生成するようにコマンドを登録

ここまでで手動でサイトマップを生成できるようになりましたが、通常は定期的にsitemap.xmlを作成しもらいたいものです。
そこで今回はcronの定期実行とLaravelのタスクスケジューラの機能を使って実現してみます。

cronは定期的に何らかのコマンドを実行するというもので、LaravelのタスクスケジューラはLaravel上の記法でどのタイミングで実行するかを記述するものとなっています。
cronでも日時や1時間ごとなど設定はかけますが、その方法だと管理が大変になるのでLaravelを使う場合は通常タスクスケジューラを使用します。
詳しくはLaravel タスクスケジュールを参照ください。

タスクスケジュールを記述する

まずはLaravelのタスクスケジュールを記述します。先程コマンドを登録したファイルをつかいます。
「追記」の行を足してください。

app/Console/Kernel.php
<?php

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
protected $commands = [
GenerateSitemap::class
];

protected function schedule(Schedule $schedule)
{
$schedule->command('sitemap:generate')->daily(); // 追記
}

protected function commands()
{
$this->load(__DIR__.'/Commands');

require base_path('routes/console.php');
}
}

$schedule->command('sitemap:generate')->daily();は見ての通り、sitemap:generateコマンドを1日ごとに実行するという記述です。
今回は1日に1回実行していきましょう。頻繁にサイトマップを更新したい場合はhourly()とかを使うと良いでしょう。

cronを設定する

最後にcronからLaravelのタスクスケジュールを実行してみましょう。

  * * * * * provider cd /path/to/app && /path/to/php artisan schedule:run >> /dev/null 2>&1

cronはご自身の環境に合わせて設定してください。crontab -eで記述しても良いですし、/etc/cron.d/適当なファイルに記述しても動きます。

  • /path/to/app: Laravelアプリケーションを配置したディレクトリ
  • /path/to/php: PHPのコマンドのパス

上記はご自身の環境に合わせて設定してください。


このcronは毎分laravelのタスクスケジュールを実行していますね。
毎分実行することによって、分毎、時毎、日毎でも実行出来ると言った具合です。今回は1日ごとに実行されます。

検証するのであれば、daily()の代わりにeveryMinute()を使っても良いですね。

これでsitemap.xmlの生成は完了です。サイトマップを作成したならgoogle search consoleに登録するようにしましょう。google botが定期的に覗きに来てくれますよ。

 

質問等はこちらで受け付けています。