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

Object Routing Bundle Laravel Package

benjam1/object-routing-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the bundle to composer.json under require:

    "benjam1/object-routing-bundle": "^1.0"
    

    Run:

    composer update benjam1/object-routing-bundle
    
  2. Enable the Bundle Register BGObjectRoutingBundle in config/bundles.php:

    return [
        // ...
        Benjam1\ObjectRoutingBundle\BGObjectRoutingBundle::class => ['all' => true],
    ];
    
  3. First Use Case: Route by Object Define a route that accepts an object (e.g., App\Entity\Product) as a parameter:

    # config/routes.yaml
    product_show:
        path: /product/{product}
        controller: App\Controller\ProductController::show
        requirements:
            product: ^\d+$  # Regex to match object ID (or custom logic)
    

    In your controller, type-hint the object:

    use App\Entity\Product;
    
    public function show(Product $product): Response
    {
        return $this->render('product/show.html.twig', ['product' => $product]);
    }
    
  4. Configure the Router Add the object_router to your router configuration (e.g., config/packages/framework.yaml):

    framework:
        router:
            object_router:
                enabled: true
                resolver: 'doctrine'  # or 'custom'
    

Implementation Patterns

Core Workflow: Object-Based Routing

  1. Define Routes with Object Parameters Use object type-hinting in route definitions (e.g., {product}) and let the bundle resolve the object from the request (e.g., via Doctrine or a custom resolver).

  2. Resolver Integration

    • Doctrine Resolver: Fetch entities by ID from the database.
      # config/packages/bg_object_routing.yaml
      bg_object_routing:
          resolvers:
              doctrine:
                  enabled: true
                  entity_manager: 'default'
      
    • Custom Resolver: Implement JMS\Router\ResolverInterface for bespoke logic (e.g., API clients, external services).
  3. Dynamic Route Generation Generate URLs from objects in templates or controllers:

    {{ path('product_show', { product: product }) }}
    
    $url = $this->generateUrl('product_show', ['product' => $product]);
    
  4. Nested Objects Route to nested resources (e.g., product/{product}/review/{review}):

    product_review_show:
        path: /product/{product}/review/{review}
        controller: App\Controller\ReviewController::show
    
    public function show(Product $product, Review $review): Response
    
  5. Validation and Constraints Use Symfony’s validator to enforce constraints on routed objects:

    use Symfony\Component\Validator\Constraints as Assert;
    
    #[Assert\Type(type: Product::class)]
    public function show(Product $product): Response
    

Integration Tips

  1. Symfony Forms Bind routed objects to forms:

    $form = $this->createForm(ProductType::class, $product);
    
  2. API Platform Combine with API Platform for automatic route generation:

    # config/packages/api_platform.yaml
    api_platform:
        routing:
            resource_collection: true
            resource_item: true
    
  3. Event Listeners Intercept object resolution with events:

    // src/EventListener/ObjectResolverListener.php
    public function onResolve(JMS\Router\Event\ResolveEvent $event): void
    {
        if ($event->getParameter('product') instanceof Product) {
            // Custom logic (e.g., caching, permissions)
        }
    }
    

    Register in services.yaml:

    services:
        App\EventListener\ObjectResolverListener:
            tags:
                - { name: kernel.event_listener, event: jms.router.resolve, method: onResolve }
    
  4. Testing Mock resolvers in tests:

    $container->get('jms.router.object_resolver')->setResolver(
        new TestResolver($mockProduct)
    );
    

Gotchas and Tips

Pitfalls

  1. Resolver Configuration

    • Error: Forgetting to enable the resolver in bg_object_routing.yaml will silently fail to resolve objects. Fix: Explicitly define resolvers under bg_object_routing.resolvers.
  2. Circular Dependencies

    • Error: Routing to an object that depends on another routed object (e.g., ProductCategoryProduct) causes infinite loops. Fix: Use lazy-loading or break cycles with custom resolvers.
  3. ID Mismatches

    • Error: The route requirement (e.g., ^\d+$) doesn’t match the object’s ID field (e.g., UUID). Fix: Customize the resolver to handle non-integer IDs or adjust route requirements.
  4. Doctrine Proxy Issues

    • Error: Doctrine proxies fail to load in routed objects due to missing entity manager context. Fix: Ensure the resolver’s entity_manager is properly configured and injected.
  5. Case Sensitivity

    • Error: Route parameters are case-sensitive (e.g., {Product} vs {product}). Fix: Standardize parameter names in routes and controllers.

Debugging

  1. Enable Router Debugging Add to config/packages/dev/framework.yaml:

    framework:
        router:
            debug: true
    

    Check logs for resolution errors in var/log/dev.log.

  2. Dump Resolved Objects Use Symfony’s var dumper in controllers:

    dump($product); // Inspect resolved object
    
  3. Resolver Priority

    • Issue: Multiple resolvers may conflict.
    • Fix: Order resolvers by priority in bg_object_routing.yaml:
      bg_object_routing:
          resolvers:
              doctrine: ~
              custom: ~
          priority: ['doctrine', 'custom']  # Lower priority runs first
      

Extension Points

  1. Custom Resolver Implement JMS\Router\ResolverInterface:

    class CustomResolver implements ResolverInterface
    {
        public function resolve(Request $request, Parameter $parameter): mixed
        {
            // Custom logic (e.g., API call, cache lookup)
            return $this->fetchFromExternalService($parameter->getName());
        }
    }
    

    Register in services.yaml:

    services:
        App\Resolver\CustomResolver:
            tags:
                - { name: jms.router.resolver, priority: 10 }
    
  2. Override Default Router Extend the router to add custom logic:

    class CustomRouter extends JMS\Router\Router
    {
        protected function doGenerate(array $parameters, array $context = []): string
        {
            // Custom URL generation
        }
    }
    

    Register as a service and replace the default router.

  3. Event Subscribers Extend resolution with subscribers:

    class ObjectResolverSubscriber implements EventSubscriberInterface
    {
        public static function getSubscribedEvents(): array
        {
            return [
                JMS\Router\Event\ResolveEvent::class => 'onResolve',
            ];
        }
    
        public function onResolve(ResolveEvent $event): void
        {
            // Modify resolved object or parameters
        }
    }
    

Configuration Quirks

  1. Entity Manager Aliases

    • Issue: Using non-default entity managers (e.g., custom_em) requires explicit configuration:
      bg_object_routing:
          resolvers:
              doctrine:
                  entity_manager: 'custom_em'
      
  2. Parameter Binding

    • Issue: Objects with the same class name but different namespaces may cause conflicts.
    • Fix: Use fully qualified class names in routes:
      product_show:
          path: /product/{App\Entity\Product}
      
  3. Caching

    • Tip: Enable router caching for performance:
      framework:
          router:
              cache_warmer: true
      
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.
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
atriumphp/atrium