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

Routing Bundle Laravel Package

symfony-cmf/routing-bundle

Symfony CMF Routing Bundle adds advanced, dynamic routing to Symfony using a content repository. Supports route documents, redirects, nested routes, locale-aware patterns, and custom route providers to manage URLs from CMS content or databases.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the bundle to your composer.json:

    composer require symfony-cmf/routing-bundle
    

    Register it in config/bundles.php:

    return [
        // ...
        SymfonyCmf\Bundle\RoutingBundle\RoutingBundle::class => ['all' => true],
    ];
    
  2. Basic Configuration Configure the bundle in config/packages/symfony_cmf_routing.yaml:

    symfony_cmf_routing:
        chain_router:
            routers_by_id:
                router.default: ~
                router.dynamic: symfony_cmf_routing.dynamic_router
        dynamic_router:
            persistence:
                phpcr: ~  # or 'doctrine_orm', 'doctrine_mongodb', etc.
    
  3. First Use Case: Dynamic Routes from Database

    • Define a route entity (e.g., Route with path, controller, priority fields).
    • Annotate your controller with @Route (or use YAML/XML) and configure the dynamic router to fetch routes from your ORM/ODM.
    • Example route entity (Doctrine ORM):
      use Doctrine\ORM\Mapping as ORM;
      
      #[ORM\Entity]
      class Route
      {
          #[ORM\Id, ORM\Column(type: 'integer')]
          private ?int $id;
      
          #[ORM\Column(type: 'string')]
          private string $path;
      
          #[ORM\Column(type: 'string')]
          private string $controller;
      
          #[ORM\Column(type: 'integer')]
          private int $priority = 0;
      }
      
    • Configure the dynamic router in config/packages/symfony_cmf_routing.yaml:
      dynamic_router:
          persistence:
              orm:
                  route_repository: 'App\Repository\RouteRepository'
      

Implementation Patterns

1. Chain Router Workflow

  • Purpose: Combine multiple routers (e.g., static YAML routes + dynamic DB routes) into a single router.
  • Pattern:
    • Define routers in routers_by_id (e.g., router.default for Symfony’s default router, router.dynamic for DB routes).
    • The chain router delegates to routers in order of priority (higher priority first).
    • Example:
      chain_router:
          routers_by_id:
              router.dynamic: symfony_cmf_routing.dynamic_router  # High priority
              router.default: ~  # Fallback
      

2. Dynamic Router Integration

  • Use Case: Load routes from a database or external source at runtime.
  • Steps:
    1. Define a Route Provider: Implement SymfonyCmf\Routing\RouteProviderInterface to fetch routes from your data source.
      use SymfonyCmf\Routing\RouteProviderInterface;
      
      class DoctrineRouteProvider implements RouteProviderInterface
      {
          public function getRoutes(): array
          {
              return $this->routeRepository->findAll()->toArray();
          }
      }
      
    2. Configure the Provider:
      dynamic_router:
          persistence:
              orm:
                  route_provider: 'App\Provider\DoctrineRouteProvider'
      
    3. Cache Routes (Optional): Enable caching to avoid querying the database on every request:
      dynamic_router:
          cache:
              enabled: true
              lifetime: 3600  # Cache for 1 hour
      

3. Route Prioritization

  • Pattern: Use the priority field (or custom logic) to determine route matching order.
  • Example:
    • Routes with higher priority values are matched first.
    • In your Route entity, set a default or dynamic priority:
      #[ORM\Column(type: 'integer')]
      private int $priority = 100; // Higher = matched first
      

4. Hybrid Routing (Static + Dynamic)

  • Workflow:
    1. Use the chain router to combine static (YAML/XML) and dynamic (DB) routes.
    2. Static routes act as fallbacks or for non-dynamic paths.
    3. Dynamic routes override static ones if they match first (priority-based).
  • Example Configuration:
    chain_router:
        routers_by_id:
            router.dynamic: symfony_cmf_routing.dynamic_router  # DB routes (high priority)
            router.yaml: symfony_cmf_routing.yaml_router       # Static routes (low priority)
    

5. Custom Route Objects

  • Pattern: Extend SymfonyCmf\Routing\RouteObjectInterface for custom route logic.
  • Example:
    use SymfonyCmf\Routing\RouteObjectInterface;
    
    class CustomRoute implements RouteObjectInterface
    {
        private string $path;
        private string $controller;
        private array $requirements;
    
        public function getPath(): string { return $this->path; }
        public function getController(): string { return $this->controller; }
        public function getRequirements(): array { return $this->requirements; }
    }
    
  • Register with the Dynamic Router:
    dynamic_router:
        persistence:
            custom:
                route_class: 'App\Routing\CustomRoute'
                provider: 'App\Provider\CustomRouteProvider'
    

Gotchas and Tips

1. Debugging Route Matching

  • Issue: Routes aren’t matching as expected.
  • Debugging Steps:
    1. Check Router Order: Ensure the chain router’s routers_by_id order is correct (higher priority first).
    2. Inspect Dynamic Routes: Dump the routes loaded by the dynamic router:
      $router = $container->get('router');
      $routes = $router->getRouteCollection()->getResources();
      dump($routes);
      
    3. Verify Route Priorities: Higher priority routes override lower ones. Adjust the priority field in your route entity.
    4. Enable Router Debugging: Use Symfony’s router debug dump:
      php bin/console debug:router
      

2. Caching Quirks

  • Gotcha: Dynamic router caching can cause stale routes if not invalidated.
  • Solutions:
    • Manual Cache Clear: Clear the cache when routes change:
      php bin/console cache:clear
      
    • Event-Based Invalidation: Listen to route updates and clear the cache:
      use Symfony\Component\EventDispatcher\EventSubscriberInterface;
      use SymfonyCmf\Routing\Event\RouteUpdateEvent;
      
      class RouteCacheSubscriber implements EventSubscriberInterface
      {
          public static function getSubscribedEvents()
          {
              return [
                  RouteUpdateEvent::NAME => 'onRouteUpdate',
              ];
          }
      
          public function onRouteUpdate(RouteUpdateEvent $event)
          {
              $this->cacheClearer->clear('cmf_routing');
          }
      }
      
    • Cache Lifetime: Set a reasonable lifetime in config (e.g., 3600 seconds).

3. Performance Considerations

  • Gotcha: Querying the database for routes on every request is slow.
  • Optimizations:
    • Cache Dynamic Routes: Enable caching in config (see above).
    • Batch Loading: Fetch all routes in one query (e.g., using DQL SELECT with ORDER BY priority DESC).
    • Denormalization: Store routes in a denormalized table for faster reads.

4. Route Object Mapping

  • Gotcha: Incorrect mapping between your route entity and RouteObjectInterface causes errors.
  • Fix:
    • Ensure your route entity implements RouteObjectInterface or use a mapper:
      use SymfonyCmf\Routing\RouteObjectMapperInterface;
      
      class DoctrineRouteMapper implements RouteObjectMapperInterface
      {
          public function createRouteObject(array $data): RouteObjectInterface
          {
              return new CustomRoute(
                  $data['path'],
                  $data['controller'],
                  $data['requirements'] ?? []
              );
          }
      }
      
    • Configure the mapper in config/packages/symfony_cmf_routing.yaml:
      dynamic_router:
          persistence:
              orm:
                  route_mapper: 'App\Mapper\DoctrineRouteMapper'
      

5. Symfony 6+ Compatibility

  • Gotcha: Some older versions of the bundle may not support Symfony 6’s new router system.
  • Workarounds:
    • Use the latest version of the bundle (check composer.json for Symfony 6 compatibility).
    • If issues arise, manually patch the Router service to work with Symfony 6’s RouterInterface.

6. Extending the Bundle

  • Extension Points:
    • Custom Route Providers: Implement RouteProviderInterface for non-DB sources (e.g., API, flat files).
    • Custom Route Matchers: Extend SymfonyCmf\Routing\RouteMatcherInterface for
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.
dmstr/symfony-system-resources-bundle
dmstr/symfony-job-queue-bundle
dmstr/openapi-json-schema-bundle
dmstr/keycloak-security-bundle
dmstr/doctrine-audit-log-bundle
dmstr/api-platform-utils-bundle
dmstr/api-configuration-bundle
chrisdev/ux-components
baks-dev/finances
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager