Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Sitemap Laravel Package

watson/sitemap

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require watson/sitemap
    

    Publish the config file (optional):

    php artisan vendor:publish --provider="Watson\Sitemap\SitemapServiceProvider"
    
  2. First Use Case: Generate a basic sitemap for a Post model:

    use Watson\Sitemap\SitemapGenerator;
    use Watson\Sitemap\Items\Url;
    
    $sitemap = SitemapGenerator::create()
        ->get('posts')
        ->setCallback(function () {
            return Post::all()->map(function ($post) {
                return Url::create('/posts/' . $post->slug)
                    ->setLastModificationDate($post->updated_at)
                    ->setChangeFrequency(Url::CHANGE_FREQUENCY_DAILY)
                    ->setPriority(0.8);
            });
        });
    
    return $sitemap->render();
    
  3. Where to Look First:

    • Facade API in the README.
    • config/sitemap.php for configuration options.
    • app/Http/Controllers/SitemapController.php (if using the default route).

Implementation Patterns

Core Workflows

  1. Dynamic Sitemap Generation: Use setCallback() to dynamically fetch URLs from your database or API:

    $sitemap->setCallback(function () {
        return Cache::remember('sitemap_posts', now()->addHours(6), function () {
            return Post::published()->get()->map(fn ($post) => Url::create(...));
        });
    });
    
  2. Sitemap Indexes: Split large sitemaps into indexes (Google recommends <50,000 URLs per sitemap):

    $index = SitemapGenerator::create('index')
        ->setCallback(function () {
            return [
                Url::create('/sitemap-posts-1.xml'),
                Url::create('/sitemap-posts-2.xml'),
            ];
        });
    
  3. Route-Based Sitemaps: Generate sitemaps from Laravel routes:

    $sitemap->get('routes')->setCallback(function () {
        return collect(Route::getRoutes()->getRoutes())->map(fn ($route) => Url::create($route->uri));
    });
    
  4. Integration with Laravel Routes: Add a route in routes/web.php:

    Route::get('/sitemap.xml', [SitemapController::class, 'index']);
    

Advanced Patterns

  • Conditional URL Generation: Use closures to conditionally include URLs:

    $sitemap->setCallback(function () {
        return Post::all()->filter(fn ($post) => $post->isPublic)->map(...);
    });
    
  • Priority & Frequency: Set dynamic priorities/frequencies based on business logic:

    $priority = $post->isFeatured ? 1.0 : 0.5;
    Url::create(...)->setPriority($priority);
    
  • Caching: Cache generated sitemaps to reduce server load:

    $sitemap->setCallback(function () {
        return Cache::remember('sitemap_cache_key', now()->addHours(1), function () {
            return Post::all()->map(...);
        });
     });
    
  • Custom XML Attributes: Extend Url to add custom attributes:

    class CustomUrl extends Url {
        public function setVideo($videoUrl) {
            $this->addAttribute('video', $videoUrl);
            return $this;
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Memory Limits: Generating large sitemaps (>10,000 URLs) may hit PHP memory limits. Use chunking or caching:

    $sitemap->setCallback(function () {
        return Post::chunk(1000, function ($posts) {
            return $posts->map(...);
        });
    });
    
  2. LastModificationDate: Ensure dates are in DateTime format or ISO-8601 strings. Avoid timestamps:

    // Bad: $post->updated_at (Carbon instance)
    // Good:
    Url::create(...)->setLastModificationDate($post->updated_at->toAtomString());
    
  3. Duplicate URLs: Use setChangeFrequency(Url::CHANGE_FREQUENCY_YEARLY) for static pages to avoid penalties.

  4. Route Caching: If using get('routes'), clear route cache (php artisan route:clear) after changes.

  5. Index Depth: Google recommends keeping sitemap indexes shallow (no nested indexes).

Debugging

  • Validate XML: Use an online validator (e.g., XML Validation) to check for malformed tags. Common issues:

    • Missing lastmod or priority attributes.
    • Invalid URLs (e.g., absolute paths like http://example.com instead of /).
  • Log Generation: Enable logging in config/sitemap.php:

    'log' => true,
    

    Check storage/logs/laravel.log for errors.

Configuration Quirks

  1. Default Options: Override defaults in config/sitemap.php:

    'default_priority' => 0.5,
    'default_change_frequency' => \Watson\Sitemap\Items\Url::CHANGE_FREQUENCY_WEEKLY,
    
  2. Custom Storage: Save sitemaps to disk or S3:

    $sitemap->store('sitemap.xml', 'public');
    // Or with S3:
    $sitemap->store('sitemap.xml', 's3', ['disk' => 's3']);
    
  3. Locale Support: Generate multilingual sitemaps by prefixing URLs:

    Url::create('/en/posts/' . $post->slug)->setLanguage('en');
    

Extension Points

  1. Custom Items: Extend the Url class for non-standard sitemap types (e.g., ImageUrl):

    class ImageUrl extends \Watson\Sitemap\Items\Url {
        public function setImageLoc($loc) {
            $this->addAttribute('image:loc', $loc);
            return $this;
        }
    }
    
  2. Event Listeners: Trigger sitemap regeneration after model updates:

    Post::observe(PostObserver::class);
    
    class PostObserver {
        public function saved(Post $post) {
            event(new PostUpdated($post));
        }
    }
    
    // In an event listener:
    event(PostUpdated::class, function () {
        Cache::forget('sitemap_cache_key');
    });
    
  3. Testing: Mock the sitemap generator in tests:

    $this->partialMock(SitemapGenerator::class, ['render'])
        ->shouldReceive('render')
        ->once()
        ->andReturn('<urlset>...</urlset>');
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle