【Laravel9】サイトマップを動的に作る【更新版】

まぐろ

過去の記事でサイトマップを動的に作る方法を紹介したが、
どうやらパッケージの更新が数年前で止まってる・・・

そのためLaravel9以降で未対応という問題が発生したので
別のパッケージを使用して作成していく

(過去の記事)

composerでパッケージインストール

composer require spatie/laravel-sitemap

  • デフォルトのオプションを変更したい場合は下記で設定ファイルを生成
php artisan vendor:publish --provider="Spatie\Sitemap\SitemapServiceProvider" --tag=sitemap-config

config/sitemap.phpが生成されるので、そこの設定を変更すればOK

サイトマップ表示用のルーティング作成

  • routes/web.php
Route::get('/sitemap', [App\Http\Controllers\SitemapController::class, 'index'])->name('sitemap');

サイトマップ作成用のController作成

  • app/Http/Controllers/SitemapController
<?php

namespace App\Http\Controllers;

use Spatie\Sitemap\Sitemap;
use Spatie\Sitemap\Tags\Url;
use App\Models\Post;

class SitemapController extends Controller
{
    /**
     * @return \Illuminate\Http\RedirectResponse
     */
    public function index()
    {
        $sitemap = Sitemap::create();
        
        // Topページ
        $sitemap->add(Url::create(route('top.index'))
                ->setLastModificationDate(now())
                ->setChangeFrequency(Url::CHANGE_FREQUENCY_ALWAYS)
                ->setPriority(1.0));

        // 記事一覧
        $sitemap->add(Url::create(route('posts.index'))
            ->setLastModificationDate(now())
            ->setChangeFrequency(Url::CHANGE_FREQUENCY_WEEKLY)
            ->setPriority(0.8));
       
        // 固定ページ
        $sitemap->add(Url::create(route('about'))
            ->setLastModificationDate(now())
            ->setChangeFrequency(Url::CHANGE_FREQUENCY_MONTHLY)
            ->setPriority(0.5));

        // サイトマップをxmlへ書き込み
        $sitemap->writeToFile(public_path('sitemap.xml'));

        // xmlを表示
        return redirect('/sitemap.xml');
    }
}

Url::createの部分は相対パスでもオッケー

 $sitemap->add(Url::create('/about')
            ->setLastModificationDate(now())
            ->setChangeFrequency(Url::CHANGE_FREQUENCY_MONTHLY)
            ->setPriority(0.5));

これで/sitemapにアクセスすると、
サイトマップ更新 & sitemap.xmlの表示が行われる

動的なページを自動生成したい場合

記事詳細など、idごとに生成されるページを一括生成したい場合

  • 対象のモデルファイルを改修 - app/Model/Post.php
// ...(省略)
use Spatie\Sitemap\Contracts\Sitemapable; // ★ 追加
use Spatie\Sitemap\Tags\Url; // ★ 追加

class Post extends Model implements Sitemapable // ★ implementsを追加
{
    use HasFactory;

    protected $guarded = ['id'];

    // ★ 追加
    public function toSitemapTag(): Url | string | array
    {
        // 詳細画面へのルーティングを記載
        return route('posts.show', $this);
    }
}
  • サイトマップ生成部分
$sitemap->add(Post::all());

これで詳細ページが動的に追加される、便利

今回パッケージの機能を利用する事で下記のようにソースの簡略化ができた

// 1から実装する場合
Material::all()->each(function (Material $material) use ($sitemap) {
  $sitemap->add(Url::create(route('materials.show', compact('material')))
    ->setLastModificationDate($material->updated_at)
    ->setChangeFrequency(Url::CHANGE_FREQUENCY_DAILY)
    ->setPriority(0.8));
});

// 今回の機能を利用する場合
$sitemap->add(Post::all());

定期的にcronでサイトマップを生成する場合

上記のように毎回アクセス時に生成・リダイレクトするんじゃなくて、
裏側で定期的にサイトマップを更新したい場合

  • コマンド作成
php artisan make:command GenerateSitemap

  • app/Console/Commands/GenerateSitemap.php
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Models\Post;
use Spatie\Sitemap\Sitemap;
use Spatie\Sitemap\Tags\Url;

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

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Generate the sitemap.';

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $sitemap = Sitemap::create();

        // Topページ
        $sitemap->add(Url::create(route('top.index'))
            ->setLastModificationDate(now())
            ->setChangeFrequency(Url::CHANGE_FREQUENCY_ALWAYS)
            ->setPriority(1.0));

        // 記事一覧
        $sitemap->add(Url::create(route('posts.index'))
            ->setLastModificationDate(now())
            ->setChangeFrequency(Url::CHANGE_FREQUENCY_WEEKLY)
            ->setPriority(0.8));

        // 記事詳細
        $sitemap->add(Post::all());

        // 固定ページ
        $sitemap->add(Url::create(route('about'))
            ->setLastModificationDate(now())
            ->setChangeFrequency(Url::CHANGE_FREQUENCY_MONTHLY)
            ->setPriority(0.5));

        // サイトマップをxmlへ書き込み
        $sitemap->writeToFile(public_path('sitemap.xml'));
    }
}

これで、php artisan sitemap:generateを叩くとサイトマップが生成されるようになった

  • 最後に、app/Console/Kernel.php にスケジュール登録しておく
// ...(省略)...
protected function schedule(Schedule $schedule)
{
    // ★ 毎日サイトマップを更新する
    $schedule->command('sitemap:generate')->daily();
}

\ 案件のご依頼・ご相談はこちらから /