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 Bundle Laravel Package

ecourty/sitemap-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require ecourty/sitemap-bundle
    

    Enable the bundle in config/bundles.php:

    return [
        // ...
        EdouardCourty\SitemapBundle\EdouardCourtySitemapBundle::class => ['all' => true],
    ];
    
  2. Basic Configuration: Add a minimal config/packages/edouard_courty_sitemap.yaml:

    edouard_courty_sitemap:
        sitemaps:
            default:
                routes:
                    - path: '/'
                      priority: 1.0
                      changefreq: 'daily'
    
  3. First Use Case: Generate a static sitemap via CLI:

    php bin/console edouard-courty:sitemap:generate default
    

    Output will be saved to public/sitemap.xml (default location).


Implementation Patterns

Dynamic Generation (Controller)

Use the SitemapGenerator service to dynamically generate sitemaps in a controller:

use EdouardCourty\SitemapBundle\Generator\SitemapGenerator;

class SitemapController extends AbstractController
{
    public function generate(SitemapGenerator $generator): Response
    {
        return $generator->generate('default');
    }
}
  • Route it:
    # config/routes.yaml
    sitemap:
        path: /sitemap.xml
        controller: App\Controller\SitemapController::generate
    

Static Generation (Command)

Leverage the CLI command for scheduled generation (e.g., via cron):

# Generate all configured sitemaps
php bin/console edouard-courty:sitemap:generate

# Generate a specific sitemap
php bin/console edouard-courty:sitemap:generate default
  • Automate with cron:
    0 3 * * * cd /path/to/project && php bin/console edouard-courty:sitemap:generate >> /dev/null 2>&1
    

Dynamic Entities

Configure Doctrine entities for dynamic sitemap entries:

edouard_courty_sitemap:
    sitemaps:
        blog:
            entities:
                - App\Entity\Post
                - App\Entity\Category
            entity_options:
                App\Entity\Post:
                    route: 'post_show'
                    route_parameters:
                        id: 'id'
                    priority: 0.8
                    changefreq: 'weekly'
                    dql: 'WHERE p.published = true'

Sitemap Index

Split large sitemaps into an index:

edouard_courty_sitemap:
    sitemaps:
        index:
            index:
                mode: 'auto'  # or 'manual'
                sitemaps:
                    - 'default'
                    - 'blog'

Gotchas and Tips

Pitfalls

  1. Memory Issues:

    • Avoid loading large datasets into memory. Use dql filters to limit results:
      dql: 'WHERE p.createdAt > :date LIMIT 1000'
      parameters:
          date: '2023-01-01'
      
    • For very large datasets, consider paginated queries via custom repositories (see below).
  2. Route Parameter Mismatches:

    • Ensure route_parameters match the actual route definition. Example:
      # Correct (matches `post_show` route)
      route_parameters:
          id: 'id'
      
      # Incorrect (will fail silently)
      route_parameters:
          slug: 'id'  # Mismatch!
      
  3. Caching Headers:

    • Static sitemaps lack cache headers by default. Add them in your public/sitemap.xml .htaccess:
      <FilesMatch "sitemap\.xml">
          Header set Cache-Control "public, max-age=86400"
      </FilesMatch>
      

Debugging

  1. Validate XML: Use an online validator (e.g., XML Validation) to check generated output for errors.

  2. Log Queries: Enable Doctrine logging to debug DQL issues:

    # config/packages/dev/doctrine.yaml
    doctrine:
        dbal:
            logging: true
            profiling: true
    
  3. Check File Permissions: Ensure the public/ directory is writable:

    chmod -R 775 public/
    

Extension Points

  1. Custom URL Providers: Extend functionality by creating a custom provider:

    namespace App\Sitemap;
    
    use EdouardCourty\SitemapBundle\Provider\UrlProviderInterface;
    
    class CustomUrlProvider implements UrlProviderInterface
    {
        public function getUrls(): array
        {
            return [
                ['loc' => 'https://example.com/custom-page', 'priority' => 0.5],
            ];
        }
    }
    

    Register it in config/packages/edouard_courty_sitemap.yaml:

    edouard_courty_sitemap:
        providers:
            custom:
                class: App\Sitemap\CustomUrlProvider
                priority: 100
    
  2. Custom Repository Methods: Override entity queries in a custom repository:

    namespace App\Repository;
    
    use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
    use Doctrine\Persistence\ManagerRegistry;
    
    class PostRepository extends ServiceEntityRepository
    {
        public function findPublishedPosts(): array
        {
            return $this->createQueryBuilder('p')
                ->where('p.published = :published')
                ->setParameter('published', true)
                ->getQuery()
                ->getResult();
        }
    }
    

    Reference it in config:

    edouard_courty_sitemap:
        sitemaps:
            blog:
                entities:
                    - App\Entity\Post
                entity_options:
                    App\Entity\Post:
                        repository_method: 'findPublishedPosts'
    
  3. Streaming Large Datasets: For entities with >10,000 records, use cursor iteration in a custom provider:

    use Doctrine\ORM\AbstractQuery;
    
    class LargeDatasetProvider implements UrlProviderInterface
    {
        public function getUrls(): array
        {
            $em = $this->container->get('doctrine')->getManager();
            $qb = $em->createQueryBuilder()
                ->select('p')
                ->from('App\Entity\Post', 'p')
                ->where('p.published = :published')
                ->setParameter('published', true);
    
            $query = $qb->getQuery();
            $query->setHint(AbstractQuery::HINT_FORCE_PARTIAL_LOAD, true);
    
            $results = $query->iterate();
            $urls = [];
    
            foreach ($results as $result) {
                $post = $result[0];
                $urls[] = [
                    'loc' => $this->generateUrl('post_show', ['id' => $post->getId()]),
                    'priority' => 0.7,
                ];
            }
    
            return $urls;
        }
    }
    

Configuration Quirks

  1. Priority/Changefreq Validation: Values must adhere to sitemap standards:

    • priority: 0.0 to 1.0 (float).
    • changefreq: always, hourly, daily, weekly, monthly, yearly, or never.
  2. Route Parameter Types: Ensure parameters match the route’s expected type (e.g., int vs. string):

    # Correct for integer ID
    route_parameters:
        id: 'id'
    
    # Incorrect for string slug
    route_parameters:
        id: 'id'  # Fails if route expects slug
    
  3. Sitemap Index Modes:

    • auto: Generates index if >50 URLs.
    • manual: Only generates index if explicitly configured.
    • disabled: Never generates an index.
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky