ldc-sitemap-generator/README.md
Jérémy Munsch 05840b58ff
feat(command): add queue option for sitemap generation
- Introduced a new `--queue` option to the `uwil:sitemap:refresh` command.
- Added `GenerateSitemapJob` for handling sitemap generation in the background.
- Updated service provider to schedule the job with the configured cron expression.
- Enhanced tests to cover new job dispatching functionality.
2026-10-15 16:34:00 +02:00

4.3 KiB

Refresh Sitemap

Generates and refreshes your sitemap.xml using a configuration file.

Supports localized routes out of the box with DefaultRouteLocalizer and optionally integrates with mcamara/laravel-localization.

Requirements

  • PHP ^8.5
  • Laravel / Illuminate ^13.0

Installation

Via Composer:

composer require uwil/sitemap-generator

Usage

  1. Publish the configuration file:

    php artisan vendor:publish --tag=sitemap-generator
    
  2. Adjust your settings in config/sitemap-generator.php (locales, routes, output storage disk & path, CRUD models).

  3. Test your configuration in the console:

    php artisan uwil:sitemap:refresh --dry-run
    
  4. Generate the sitemap file:

    php artisan uwil:sitemap:refresh
    

    Or dispatch the generation to the queue:

    php artisan uwil:sitemap:refresh --queue
    

A route is automatically registered to serve your generated sitemap: GET /sitemap.xml


Model Implementation

Models defined in the cruds config section must implement Uwil\SitemapGenerator\Contracts\Sitemapable.

You only need to define getLocalizedUrl(string $locale) to resolve the full URL for each configured locale. The package automatically generates the main URLs and their respective xhtml:link alternate (hreflang) tags.

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
use Spatie\Sitemap\Tags\Url;
use Uwil\SitemapGenerator\Contracts\Sitemapable;

class Product extends Model implements Sitemapable
{
    /**
     * Return the localized URL for a given locale.
     */
    public function getLocalizedUrl(string $locale): string
    {
        // Example with mcamara/laravel-localization:
        return LaravelLocalization::getURLFromRouteNameTranslated(
            $locale,
            'routes.product.show',
            ['product' => $this]
        ) ?? route('products.show', ['locale' => $locale, 'product' => $this]);
    }

    /**
     * (Optional) Custom tag definition if using Spatie's native resolution.
     */
    public function toSitemapTag(): Url|string|array
    {
        return route('products.show', $this);
    }
}

Configuration Example

In config/sitemap-generator.php:

use App\Models\Product;
use Illuminate\Database\Eloquent\Builder;

return [
    'single_pages' => [
        'homepage',
        'contact',
    ],

    'cruds' => [
        [
            'model' => Product::class,
            'model_filters' => [
                ['is_active', '=', true],
            ],
            'relation_filters' => [
                'category' => fn (Builder $query) => $query->where('published', true),
            ],
            'allow_null_relation' => ['category'],
        ],
    ],

    'supported_locales' => ['fr', 'en', 'es'],

    /**
     * Route localization strategy:
     * - 'default' (or DefaultRouteLocalizer::class): uses Laravel's standard route names with {locale} parameter.
     * - 'mcamara' (or McamaraRouteLocalizer::class): uses mcamara/laravel-localization route translations.
     * - Custom class implementing RouteLocalizerInterface.
     */
    'localizer' => 'default',

    'schedule' => true,
    'cron' => '45 15 * * *',

    'output' => [
        'storage_disk' => 'public',
        'path'         => 'sitemap.xml',
    ],
];

CRUD Relation Filters & Nullable Relations

  • model_filters: Standard Eloquent where clauses applied to the root model.
  • relation_filters: Filters applied to model relations. Supports:
    • Closure: fn (Builder $q) => $q->where('status', true)
    • array: ['status' => true]
    • string: 'is_active' (shorthand for where('is_active', true))
  • allow_null_relation: Array of relation names where models having null for this relation are still included in the sitemap (using whereDoesntHave() OR whereHas()). Relations not listed here require the related model to exist.

Security

If you discover any security-related issues, please email equipe.web@ldc.fr instead of using the issue tracker.

Changelog

See the CHANGELOG.md file for details.

Sitemap Generator was written by Uwil.

Copyright (c) 2023 and beyond Uwil.