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 Maker Laravel Package

amine-lejmi/messenger-maker

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to First Use

  1. Installation:

    composer require amine-lejmi/messenger-maker
    

    For non-Flex projects, add the bundle to config/bundles.php:

    AmineLejmi\MessengerMaker\MessengerMakerBundle::class => ['all' => true],
    
  2. Configure Services (config/services.yaml):

    services:
      _instanceof:
        AmineLejmi\MessengerMaker\Contract\CommandHandlerInterface:
          tags: ['{ name: messenger.message_handler, bus: command.bus }']
        # Repeat for QueryHandlerInterface and EventHandlerInterface as needed
    
  3. Generate Your First Message:

    php bin/console make:messenger:command SendEmailCommand
    

    Follow prompts to define properties (e.g., address, message) and transport priority.

  4. Verify Auto-Generated Files:

    • src/Messenger/Command/SendEmailCommand.php (message class with getters).
    • src/Messenger/CommandHandler/SendEmailCommandHandler.php (handler implementing CommandHandlerInterface).
  5. Dispatch the Command (e.g., in a controller):

    use Symfony\Component\Messenger\MessageBusInterface;
    
    public function __construct(private MessageBusInterface $commandBus) {}
    
    public function sendEmail(string $address, ?string $message): void
    {
        $this->commandBus->dispatch(new SendEmailCommand($address, $message));
    }
    

Implementation Patterns

Workflows

1. Message Creation Workflow

  • Command/Query/Event Generation: Use make:messenger:command, make:messenger:query, or make:messenger:event to scaffold messages with interactive prompts for properties and transports. Example:

    php bin/console make:messenger:query GetUserQuery
    

    Prompt: Define properties like userId: int and select transport (e.g., sync).

  • Handler Implementation: Implement the auto-generated interface (CommandHandlerInterface, etc.) in the handler class. The bundle ensures handlers are auto-registered with the correct bus (command.bus, query.bus, or event.bus).

  • Transport Routing: The bundle auto-updates config/packages/messenger.yaml to route messages to the selected transport (e.g., high-priority, sync).

2. Integration with Symfony Messenger

  • Bus Configuration: Define buses in config/packages/messenger.yaml:

    framework:
      messenger:
        buses:
          command.bus: ~
          query.bus: ~
          event.bus: ~
    

    Use command.bus for commands, query.bus for queries (with return types), and event.bus for events.

  • Dependency Injection: Inject the appropriate bus into services:

    public function __construct(
        private MessageBusInterface $commandBus,
        private AsyncBusInterface $eventBus
    ) {}
    
  • Middleware: Attach middleware to buses (e.g., logging, validation) in messenger.yaml:

    framework:
      messenger:
        buses:
          command.bus:
            middleware:
              - 'doctrine_transaction'
    

3. Testing Patterns

  • Unit Testing Handlers: Mock the message bus and verify handler invocations:

    $bus = $this->createMock(MessageBusInterface::class);
    $handler = new SendEmailCommandHandler();
    $bus->expects($this->once())->method('dispatch');
    $handler($command); // Assert logic in handler
    
  • Integration Testing: Use Symfony’s MessengerTestTrait or mock transports to test message flow:

    use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
    
    $serializer = $this->createMock(SerializerInterface::class);
    $this->bus->setSerializer($serializer);
    

4. Domain-Specific Patterns

  • CQRS Separation: Organize messages by domain (e.g., src/Messenger/User/Command/, src/Messenger/User/Query/). Example:

    php bin/console make:messenger:command User/DeleteUserCommand
    
  • DTOs for Complex Messages: For messages with nested data, use DTOs (e.g., UserProfileDTO) and pass them as properties:

    class UpdateUserProfileCommand {
        public function __construct(private UserProfileDTO $profile) {}
    }
    
  • Event Sourcing: Dispatch domain events after command handling:

    $this->eventBus->dispatch(new UserProfileUpdatedEvent($userId, $profile));
    

Gotchas and Tips

Pitfalls

  1. Transport Misconfiguration:

    • Issue: Forgetting to configure transports in messenger.yaml or selecting an unconfigured transport during message creation.
    • Fix: Ensure transports exist in messenger.yaml:
      framework:
        messenger:
          transports:
            high-priority: { dsn: 'sync://' }
      
      Re-run the make command to reselect a valid transport.
  2. Handler Interface Mismatch:

    • Issue: Handlers not implementing the correct interface (e.g., CommandHandlerInterface for commands) or missing the _instanceof tag in services.yaml.
    • Fix: Verify the handler implements the interface and the service tag is present:
      services:
        _instanceof:
          AmineLejmi\MessengerMaker\Contract\CommandHandlerInterface:
            tags: ['{ name: messenger.message_handler, bus: command.bus }']
      
  3. Circular Dependencies:

    • Issue: Messages referencing handlers or vice versa, causing autowiring failures.
    • Fix: Avoid circular references. Use constructor injection for dependencies:
      class SendEmailCommandHandler implements CommandHandlerInterface {
          public function __construct(private EmailService $emailService) {}
      }
      
  4. Message Routing Overrides:

    • Issue: Manual routing in messenger.yaml conflicting with auto-generated routes.
    • Fix: Prefer auto-generated routes or explicitly exclude messages from auto-routing:
      framework:
        messenger:
          routing:
            'App\Messenger\Command\SendEmailCommand': ~ # Override or exclude
      
  5. Property Type Errors:

    • Issue: Invalid property types (e.g., DateTime without DateTimeImmutable) causing generation failures.
    • Fix: Use supported types (e.g., DateTimeImmutable, array, object) or extend the bundle’s type system (see Extension Points).

Debugging Tips

  1. Check Generated Files:

    • Verify messages and handlers are created in src/Messenger/ with correct namespaces and interfaces.
  2. Validate messenger.yaml:

    • Run php bin/console debug:config messenger to inspect routing and transport configurations.
  3. Enable Messenger Debugging:

    • Add debug middleware to messenger.yaml:
      framework:
        messenger:
          buses:
            command.bus:
              middleware:
                - 'debug'
      
    • Check logs for dispatched messages: bin/console messenger:consume async -vv.
  4. Handler Invocation Issues:

    • Use bin/console debug:container to verify handlers are registered with the correct bus.
    • Test handlers in isolation:
      $handler = new SendEmailCommandHandler();
      $handler(new SendEmailCommand('test@example.com', 'Hello'));
      

Configuration Quirks

  1. Transport Priority:

    • Priorities (high-priority, low-priority) must match configured transports. Defaults to sync if none selected.
  2. Nullable Fields:

    • The bundle defaults nullable fields to false. Explicitly answer yes to prompts for nullable properties.
  3. Custom Property Types:

    • The bundle supports basic types (string, int, bool, etc.). For custom types (e.g., User), ensure they are autowireable or use FQCNs:
      New property name: user
      Field type: App\Entity\User
      

Extension Points

  1. Custom Message Templates:

    • Override the bundle’s templates by copying files from vendor/amine-lejmi/messenger-maker/src/Resources/skeleton/ to config/skeleton/messenger-maker/.
  2. Additional Property Types:

    • Extend the type system by creating a custom Type class and updating the bundle’s TypeRegistry (requires fork/modification).
  3. Custom Handlers:

    • Implement MessengerMakerEvents::POST_CREATE_MESSAGE to modify generated messages:
      use Symfony\Component\EventDispatcher\EventSubscriberInterface;
      use AmineLejmi\MessengerMaker\Event\MessengerMakerEvents;
      
      class CustomMessengerMakerSubscriber implements EventSubscriberInterface {
          public static function get
      
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.
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
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui