【Laravel8】サイトマップを動的に作る

えび

Laravelで、登録されたデータなどをもとにサイトマップの動的生成を行う

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

composer require laravelium/sitemap
php artisan vendor:publish --provider="Laravelium\Sitemap\SitemapServiceProvider"

ちなみに2021年7月現在、Laravel7のプロジェクトで上記コマンドを叩くとエラーがでる


Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Conclusion: remove laravel/framework v7.30.4
    - Conclusion: don't install laravel/framework v7.30.4
    - laravelium/sitemap 8.0.1 requires illuminate/filesystem ^8.0 -> satisfiable by illuminate/filesystem[8.x-dev, v8.0.0, v8.0.1, v8.0.2, v8.0.3, v8.0.4, v8.1.0, v8.10.0, v8.11.0, v8.11.1, v8.11.2, v8.12.0, v8.12.1, v8.12.2, v8.12.3, v8.13.0, v8.14.0, v8.15.0, v8.16.0, v8.16.1, v8.17.0, v8.17.2, v8.18.0, v8.18.1, v8.19.0, v8.2.0, v8.20.0, v8.20.1, v8.21.0, v8.22.0, v8.22.1, v8.23.1, v8.24.0, v8.25.0, v8.26.0, v8.26.1, v8.27.0, v8.28.0, v8.28.1, v8.29.0, v8.3.0, v8.30.0, v8.30.1, v8.31.0, v8.32.0, v8.32.1, v8.33.0, v8.33.1, v8.34.0, v8.35.0, v8.35.1, v8.36.0, v8.36.1, v8.36.2, v8.37.0, v8.38.0, v8.39.0, v8.4.0, v8.40.0, v8.41.0, v8.42.0, v8.42.1, v8.43.0, v8.44.0, v8.45.0, v8.45.1, v8.46.0, v8.47.0, v8.48.0, v8.48.1, v8.48.2, v8.49.0, v8.49.1, v8.49.2, v8.5.0, v8.50.0, v8.51.0, v8.52.0, v8.6.0, v8.7.0, v8.7.1, v8.8.0, v8.9.0].
    - laravelium/sitemap 8.x-dev requires illuminate/filesystem ^8.0 -> satisfiable by illuminate/filesystem[8.x-dev, v8.0.0, v8.0.1, v8.0.2, v8.0.3, v8.0.4, v8.1.0, v8.10.0, v8.11.0, v8.11.1, v8.11.2, v8.12.0, v8.12.1, v8.12.2, v8.12.3, v8.13.0, v8.14.0, v8.15.0, v8.16.0, v8.16.1, v8.17.0, v8.17.2, v8.18.0, v8.18.1, v8.19.0, v8.2.0, v8.20.0, v8.20.1, v8.21.0, v8.22.0, v8.22.1, v8.23.1, v8.24.0, v8.25.0, v8.26.0, v8.26.1, v8.27.0, v8.28.0, v8.28.1, v8.29.0, v8.3.0, v8.30.0, v8.30.1, v8.31.0, v8.32.0, v8.32.1, v8.33.0, v8.33.1, v8.34.0, v8.35.0, v8.35.1, v8.36.0, v8.36.1, v8.36.2, v8.37.0, v8.38.0, v8.39.0, v8.4.0, v8.40.0, v8.41.0, v8.42.0, v8.42.1, v8.43.0, v8.44.0, v8.45.0, v8.45.1, v8.46.0, v8.47.0, v8.48.0, v8.48.1, v8.48.2, v8.49.0, v8.49.1, v8.49.2, v8.5.0, v8.50.0, v8.51.0, v8.52.0, v8.6.0, v8.7.0, v8.7.1, v8.8.0, v8.9.0].
    - don't install illuminate/filesystem 8.x-dev|don't install laravel/framework v7.30.4
    - don't install illuminate/filesystem v8.0.0|don't install laravel/framework v7.30.4
    - don't install illuminate/filesystem v8.0.1|don't install laravel/framework v7.30.4
    - don't install illuminate/filesystem v8.0.2|don't install laravel/framework v7.30.4
    - don't install illuminate/filesystem v8.0.3|don't install laravel/framework v7.30.4
    - don't install illuminate/filesystem v8.0.4|don't install laravel/framework v7.30.4
    - don't install illuminate/filesystem v8.1.0|don't install laravel/framework v7.30.4
    - don't install illuminate/filesystem v8.10.0|don't install laravel/framework v7.30.4
(省略)

laravelium/sitemapの最新バージョンはLaravel8だから、
Laravel7だとバージョンが合わないよっていうエラー
そのため、Laravelのバージョンに応じて正しいバージョンをinstallしてあげる必要がある

Laravel8の場合: composer require laravelium/sitemap 8.*
Laravel7の場合: composer require laravelium/sitemap 7.*
Laravel6の場合: composer require laravelium/sitemap 6.*

詳細はこちら

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

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

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

例えば、TOPページと、投稿されたブログ詳細ページを対象にしたい場合

  • app/Http/Controllers/SitemapController
<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\URL;

class SitemapController extends Controller
{
    /**
     * @return \Illuminate\Contracts\View\View
     */
    public function index(Request $request)
    {
        $sitemap = App::make("sitemap");

        // Topページ
        $sitemap->add(URL::to('/'), now(), '1.0', 'always');

        // DBのデータを元に動的URL生成
        $posts = Post::query()->orderBy('updated_at', 'desc')->get();
        foreach ($posts as $post) {
            $sitemap->add(route('post.show', compact('post')), $post->updated_at, '0.8', 'monthly');
        }

        // 出力
        return $sitemap->render('xml');
        // XMLファイルで出力する場合
        // $sitemap->store('xml', 'mysitemap');
    }
}
補足

$sitemap->add()の引数に指定できるのは、順番に以下の内容
今回は更新頻度までを設定してる

  1. URL
  2. 更新日
  3. 優先度
  4. 更新頻度
  5. 画像
  6. タイトル
  7. transactions
  8. 動画
  9. GoogleNews
  10. alternate設定

サイトマップにアクセスしてみる

  • {サイトURL}/sitemapにアクセスすると、サイトマップが表示される
  • もし「Argument 1 passed to Laravelium\Sitemap\Sitemap::__construct() must be of the type array, null given」エラーが出た場合、
    キャッシュを削除してあげるとOK
php artisan config:clear
php artisan cache:clear
php artisan config:cache

ページの表示をカスタマイズしたい場合

デフォルトだと、このように「Generated by ・・」などの文言が表示される

ここを変更したい場合は、下記ファイルを編集すればOK

  • public/vendor/sitemap/styles/xml.xsl
<!-- 省略 -->
<body>
	<div id="content">
	  	<h2>XML Sitemap</h2>
		<p class="expl">Generated by <a href="https://gitlab.com/Laravelium/Sitemap" target="_blank" title="Sitemap generator for Laravel">laravelium-sitemap</a>. This is styled xml sitemap, sorted by update date.</p>
		<p class="expl">This sitemap contains <xsl:value-of select="count(s:urlset/s:url)"/> URLs.</p>
	    <table id="sitemap" class="tablesorter" border="1" cellpadding="3">
		<thead>
	      <tr bgcolor="#9acd32">
	        <th style="text-align:left">URL</th>
	        <th style="text-align:left">Alternates</th>
			<th style="text-align:left">Images</th>
			<th style="text-align:left">Videos</th>
	        <th style="text-align:left">Priority</th>
	        <th style="text-align:left">Update freq</th>
	        <th style="text-align:left">Updated at</th>
	      </tr>
		</thead>
		<tbody>
	      <xsl:for-each select="s:urlset/s:url">
	      <tr>
	        <td class="url"><xsl:value-of select="s:loc"/></td>
	        <td><xsl:value-of select="count(xhtml:link)"/></td>
	        <td><xsl:value-of select="count(image:image)"/></td>
	        <td><xsl:value-of select="count(video:video)"/></td>
	        <td><xsl:value-of select="concat(s:priority*100,'%')"/></td>
	        <td><xsl:value-of select="s:changefreq"/></td>
	        <td><xsl:value-of select="concat(substring(s:lastmod,0,11),concat(' ', substring(s:lastmod,12,5)))"/></td>
	      </tr>
	      </xsl:for-each>
		</tbody>
	    </table>
	    <footer></footer>
	</div>
</body>
<!-- 省略 -->