Installation
Add the bundle to your composer.json:
composer require contextualcode/site-link-bundle
Enable it in config/bundles.php:
return [
// ...
ContextualCode\SiteLinkBundle\SiteLinkBundle::class => ['all' => true],
];
Configuration
Update config/packages/contextualcode_site_link.yaml to define your siteaccesses:
site_link:
siteaccesses:
- site1
- site2
default_siteaccess: site1
First Use Case Generate a cross-siteaccess link for a content item:
use ContextualCode\SiteLinkBundle\Generator\SiteLinkGenerator;
$generator = $this->container->get(SiteLinkGenerator::class);
$link = $generator->generate($content, 'site2');
Outputs a URL like: https://site2.example.com/content/123.
Link Generation in Controllers Use dependency injection to generate links dynamically:
public function showAction(Content $content, SiteLinkGenerator $generator)
{
$crossSiteLink = $generator->generate($content, 'mobile');
return $this->render('content/show.html.twig', [
'crossSiteLink' => $crossSiteLink,
]);
}
Twig Integration Access the generator in templates:
{{ app.service('contextualcode_site_link.generator').generate(content, 'admin') }}
Media Linking Handle media items (e.g., images) across siteaccesses:
$mediaLink = $generator->generateMedia($media, 'site2');
Batch Processing
Use the SiteLinkBatchGenerator for bulk operations (e.g., migrations):
$batchGenerator = $this->container->get(SiteLinkBatchGenerator::class);
$batchGenerator->process($contents, 'site2');
Symfony Event Listeners Trigger link updates on content publish/unpublish:
use ContextualCode\SiteLinkBundle\Event\SiteLinkEvent;
public function onContentPublish(SiteLinkEvent $event)
{
$event->getGenerator()->generate($event->getContent(), 'mobile');
}
Custom Link Types Extend the generator for non-standard routes:
class CustomLinkGenerator extends SiteLinkGenerator
{
public function generateCustomRoute($content, $siteaccess)
{
return $this->router->generate('custom_route', [
'id' => $content->id,
'_siteaccess' => $siteaccess,
]);
}
}
Cache Warmup Pre-generate links for critical paths:
$generator->generate($content, 'site2'); // Forces cache population
Siteaccess Mismatch
default_siteaccess is misconfigured.generate().ezplatform.siteaccess in the request context.Circular Dependencies
SiteLinkGenerator::generateSafe() to avoid infinite loops.Media URL Overrides
MediaUrlResolverInterface and is tagged correctly.Route Not Found
generate() throws RouteNotFoundException for invalid routes.try {
$link = $generator->generate($content, 'site2');
} catch (RouteNotFoundException $e) {
$this->logger->error($e->getMessage());
return null;
}
Enable Verbose Logging
Add to config/packages/monolog.yaml:
handlers:
contextualcode:
type: stream
path: "%kernel.logs_dir%/site_link.log"
level: debug
Check Generated URLs
Use debug:router to verify routes:
php bin/console debug:router --siteaccess=site2
Inspect Siteaccess Context Dump the current siteaccess in templates:
{{ dump(app('ezpublish.siteaccess')|default('unknown')) }}
Custom Generators Create a service decorator:
# config/services.yaml
ContextualCode\SiteLinkBundle\Generator\SiteLinkGenerator:
decorates: 'contextualcode_site_link.generator'
arguments: ['@contextualcode_site_link.generator.inner']
Post-Install Hooks
Use the SiteLinkEvents::POST_INSTALL event to update existing links:
$event->getDispatcher()->addListener(
SiteLinkEvents::POST_INSTALL,
function (SiteLinkEvent $event) {
$event->getGenerator()->regenerateAll('site2');
}
);
Dynamic Siteaccess Resolution
Override SiteAccessResolverInterface for logic like:
Link Validation Add a validator to check links before rendering:
use ContextualCode\SiteLinkBundle\Validator\SiteLinkValidator;
$validator = new SiteLinkValidator($generator);
if (!$validator->isValid($link, 'site2')) {
throw new \RuntimeException('Invalid cross-siteaccess link');
}
How can I help you explore Laravel packages today?