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

Messenger Bridge Bundle Laravel Package

danielkorytek/messenger-bridge-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require danielkorytek/messenger-bridge-bundle
    

    Ensure the bundle is enabled in config/bundles.php:

    return [
        // ...
        DanielKorytek\MessengerBridgeBundle\DanielKorytekMessengerBridgeBundle::class => ['all' => true],
    ];
    
  2. Configure Routing Key Middleware: Add the middleware to your messenger.yml under the desired bus (e.g., shared.message.bus):

    framework:
        messenger:
            buses:
                shared.message.bus:
                    middleware:
                        - messenger.bridge.middleware.routing_key
    
  3. Define a Custom Routing Key Resolver: Implement RoutingKeyResolverInterface and register it as a service:

    messenger.bridge.routing.app_id_routing_key_resolver:
        class: App\Message\Routing\AppIdRoutingKeyResolver
        arguments: ['@some.service']
        tags: ['container.service']
    
  4. First Use Case: Dispatch a message with a routing key (e.g., user.created). The middleware will append the locale (or other logic) dynamically:

    $bus->dispatch(new UserCreatedEvent($userId));
    

Implementation Patterns

Workflows

  1. Locale-Aware Routing: Use the RoutingKeyMiddleware to dynamically modify routing keys based on the current locale or app ID:

    # Example: Append locale to routing key
    messenger.bridge.routing.app_id_routing_key_resolver:
        class: DanielKorytek\MessengerBridgeBundle\Message\Routing\RoutingKeyResolver\AppIdRoutingKeyResolver
        arguments: ['@request_stack']
    
  2. Bus-Specific Configuration: Attach the middleware only to buses handling cross-app messages (e.g., shared.message.bus), not internal buses like command.bus.

  3. Custom Resolver Logic: Extend AppIdRoutingKeyResolver to implement business-specific rules (e.g., tenant ID, priority flags):

    class TenantAwareRoutingKeyResolver implements RoutingKeyResolverInterface
    {
        public function resolve(string $routingKey, MessageInterface $message): string
        {
            $tenantId = $message->getTenantId();
            return "tenant.$tenantId.$routingKey";
        }
    }
    
  4. Integration with Docplanner: Align routing keys with Docplanner’s messaging standard (e.g., docplanner.user.created). Use the middleware to transform internal keys (e.g., user.created) to Docplanner-compatible formats.

Tips for Daily Use

  • Debugging Routing Keys: Log the resolved routing key in your resolver for debugging:

    public function resolve(string $routingKey, MessageInterface $message): string
    {
        $resolvedKey = "prefix.$routingKey";
        \Log::debug("Resolved routing key: {$resolvedKey}", ['message' => $message]);
        return $resolvedKey;
    }
    
  • Symfony Version Compatibility: Use the correct middleware class based on your Symfony version (e.g., Symf51\RoutingKeyMiddleware for Symfony ≥ 5.1).

  • Performance: Avoid heavy logic in resolvers. Cache or pre-compute values if needed (e.g., tenant ID from a session).


Gotchas and Tips

Pitfalls

  1. Middleware Order Matters: Place messenger.bridge.middleware.routing_key before any middleware that might modify the message (e.g., handlers or serializers). Incorrect ordering can lead to unresolved routing keys.

  2. Symfony Version Mismatch: Using the wrong middleware class (e.g., RoutingKeyMiddleware for Symfony ≥ 5.1) will cause a ClassNotFoundException. Always check the README for version-specific instructions.

  3. Circular Dependencies: If your resolver depends on services that aren’t autowired (e.g., RequestStack), ensure they’re properly configured in services.yaml:

    messenger.bridge.routing.app_id_routing_key_resolver:
        arguments:
            $requestStack: '@request_stack'
    
  4. Routing Key Collisions: Poorly designed resolvers may generate duplicate or conflicting routing keys (e.g., locale.en.user.created vs. en.user.created). Test with edge cases like empty locales or IDs.

  5. Serialization Issues: The package relies on Symfony Messenger’s serializer. Ensure your messages implement MessageInterface and are properly annotated for serialization:

    #[AsMessage]
    class UserCreatedEvent implements MessageInterface
    {
        // ...
    }
    

Debugging

  • Check Resolver Output: Temporarily log the resolved routing key in your resolver to verify transformations:

    \Log::debug('Original key:', [$routingKey]);
    \Log::debug('Resolved key:', [$resolvedKey]);
    
  • Middleware Debugging: Enable Symfony’s messenger debug mode to inspect the middleware stack:

    framework:
        messenger:
            transports:
                async: '%env(MESSENGER_TRANSPORT_DSN)%'
            routing:
                'App\Message\UserCreatedEvent': async
            buses:
                shared.message.bus:
                    middleware:
                        - messenger.bridge.middleware.routing_key
                        - messenger.debug.middleware  # Add this for debugging
    
  • Transport-Level Inspection: Use a transport like doctrine or redis with logging enabled to verify messages are dispatched with the correct routing key.

Extension Points

  1. Custom Middleware: Extend RoutingKeyMiddleware to add pre/post-processing logic:

    class CustomRoutingKeyMiddleware extends RoutingKeyMiddleware
    {
        public function handle(MessageInterface $message, callable $next): void
        {
            // Pre-processing
            $resolvedKey = $this->resolver->resolve($message->getRoutingKey(), $message);
            $message->setRoutingKey($resolvedKey);
    
            // Call next middleware
            $next($message);
        }
    }
    
  2. Dynamic Resolver Selection: Use parameter bags or DI to switch resolvers based on environment or message type:

    messenger.bridge.routing_key_resolver:
        class: App\Message\Routing\DynamicRoutingKeyResolver
        arguments:
            - '%kernel.environment%'
    
  3. Event Listeners: Attach listeners to MESSENGER_MESSAGE_SENT to log or validate routing keys:

    $eventDispatcher->addListener(
        MessengerEvents::MESSAGE_SENT,
        fn (MessageSentEvent $event) => \Log::info('Sent message with key:', [$event->getMessage()->getRoutingKey()])
    );
    
  4. Testing: Mock the resolver in tests to avoid real dependencies:

    $resolver = $this->createMock(RoutingKeyResolverInterface::class);
    $resolver->method('resolve')->willReturn('test.key');
    $middleware = new RoutingKeyMiddleware($resolver);
    
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.
jayeshmepani/jpl-moshier-ephemeris-php
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