composer require nucleos/sitemap-bundle
config/bundles.php:
return [
// ...
Nucleos\SitemapBundle\NucleosSitemapBundle::class => ['all' => true],
];
config/routes.yaml:
nucleos_sitemap:
resource: "@NucleosSitemapBundle/Resources/config/routing.yml"
prefix: /
use Nucleos\SitemapBundle\Sitemap\SitemapInterface;
use Nucleos\SitemapBundle\Sitemap\SitemapUrl;
class MySitemapService
{
public function getUrls(): array
{
return [
new SitemapUrl('https://example.com/home', 'daily', '1.0', 'Homepage'),
new SitemapUrl('https://example.com/blog', 'weekly', '0.8', 'Blog'),
];
}
}
config/services.yaml:
services:
Nucleos\SitemapBundle\Sitemap\SitemapInterface: '@App\Service\MySitemapService'
Generate a sitemap for a Symfony application with dynamic routes (e.g., blog posts, product pages). Use the SitemapUrl class to define URLs with priority and change frequency, then inject the service into a controller or command to render the XML.
Service-Based Approach:
Create a service implementing SitemapInterface to fetch URLs dynamically (e.g., from a database or API). Example:
class BlogSitemapService implements SitemapInterface
{
public function getUrls(): array
{
$posts = $this->postRepository->findAllPublished();
return array_map(fn($post) => new SitemapUrl(
route('post.show', ['slug' => $post->slug]),
'weekly',
'0.9',
$post->title
), $posts);
}
}
Event-Driven Updates:
Trigger sitemap regeneration after content changes (e.g., post.published event):
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Nucleos\SitemapBundle\Event\SitemapRegenerateEvent;
class SitemapSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
'post.published' => 'onPostPublished',
];
}
public function onPostPublished(PostPublishedEvent $event)
{
$this->eventDispatcher->dispatch(new SitemapRegenerateEvent());
}
}
Caching: Cache the generated sitemap to reduce server load. Use Symfony’s cache system:
# config/packages/nucleos_sitemap.yaml
nucleos_sitemap:
cache_enabled: true
cache_lifetime: 3600 # 1 hour
Route-Based URLs:
Generate URLs using Symfony’s UrlGeneratorInterface for consistency:
$urlGenerator = $this->container->get('router');
$url = $urlGenerator->generate('post.show', ['slug' => $post->slug]);
Custom Templates:
Override the default XML template by extending the bundle’s SitemapRenderer:
{# templates/NucleosSitemapBundle/sitemap.xml.twig #}
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{% for url in urls %}
<url>
<loc>{{ url.loc }}</loc>
<lastmod>{{ url.lastmod|date('Y-m-d') }}</lastmod>
<changefreq>{{ url.changefreq }}</changefreq>
<priority>{{ url.priority }}</priority>
</url>
{% endfor %}
</urlset>
Multi-Language Support: Generate separate sitemaps for each locale using route parameters:
$url = $urlGenerator->generate('post.show', [
'slug' => $post->slug,
'_locale' => 'en',
]);
Sitemap Index:
Split large sitemaps into multiple files and generate a sitemap-index.xml:
# config/packages/nucleos_sitemap.yaml
nucleos_sitemap:
sitemap_index:
enabled: true
max_urls_per_sitemap: 5000
Conditional URL Inclusion: Filter URLs based on business logic (e.g., exclude drafts):
public function getUrls(): array
{
return array_filter($this->getAllUrls(), fn($url) => !$url->isDraft());
}
External URLs:
Include external URLs (e.g., third-party resources) with SitemapUrl:
new SitemapUrl('https://external-site.com/resource', 'monthly', '0.5', 'External Resource');
URL Generation Issues:
SitemapUrl may not resolve correctly if the route is undefined or parameters are invalid.UrlGeneratorInterface to generate absolute URLs and validate routes:
try {
$url = $urlGenerator->generate('post.show', ['slug' => $post->slug], UrlGeneratorInterface::ABSOLUTE_URL);
} catch (\Exception $e) {
// Log or skip invalid URLs
}
Caching Conflicts:
php bin/console cache:clear nucleos_sitemap
XML Validation Errors:
loc tag) may cause search engines to ignore the sitemap.Duplicate URLs:
array_unique or a SplObjectStorage to deduplicate URLs:
$urls = array_unique($this->getUrls(), SplObjectStorage::class);
Locale Mismatches:
_locale in route parameters or use the router to generate locale-aware URLs.Log Generated URLs: Enable debug logging to inspect URLs before rendering:
# config/packages/monolog.yaml
handlers:
sitemap:
type: stream
path: "%kernel.logs_dir%/sitemap.log"
level: debug
Log URLs in your SitemapInterface implementation:
$this->logger->debug('Generated sitemap URLs', ['urls' => $urls]);
Inspect Cache: Check if the cache is working as expected:
php bin/console cache:pool:list
php bin/console cache:pool:clear nucleos_sitemap
Validate XML:
Use an online tool like XML Validation to check the generated sitemap.xml.
Default Change Frequency:
The bundle defaults to 'daily' for all URLs. Override this in your SitemapUrl constructor or set a default in the bundle config:
# config/packages/nucleos_sitemap.yaml
nucleos_sitemap:
default_changefreq: 'weekly'
Priority Clamping:
The priority field in SitemapUrl is clamped between 0.0 and 1.0. Ensure values are within this range:
$priority = min(1.0, max(0.0, $yourPriorityValue));
Lastmod Precision:
The lastmod field should be in YYYY-MM-DD format. Use Symfony’s DateTime utilities to format dates:
$lastmod = $post->updatedAt->format('Y-m-d');
How can I help you explore Laravel packages today?