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

Api Platform Event Engine Bundle Laravel Package

arnedesmedt/api-platform-event-engine-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup Steps

  1. Install the Bundle

    composer require arnedesmedt/api-platform-event-engine-bundle
    

    Ensure arnedesmedt/event-engine-symfony-bundle is also installed (dependency).

  2. Configure the Bundle Add to config/bundles.php:

    return [
        // ...
        Arnedesmedt\ApiPlatformEventEngineBundle\ApiPlatformEventEngineBundle::class => ['all' => true],
    ];
    
  3. Enable Event Engine Configure arnedesmedt/event-engine-symfony-bundle in config/packages/arnedesmedt_event_engine.yaml:

    arnedesmedt_event_engine:
        event_store: 'doctrine' # or 'in-memory'
        command_bus: 'messenger'
    
  4. Define an Aggregate Create a class implementing AggregateRoot and ChangeApiResource:

    use Arnedesmedt\EventEngine\Domain\AggregateRoot;
    use Arnedesmedt\EventEngine\Domain\ChangeApiResource;
    
    class Order implements AggregateRoot, ChangeApiResource
    {
        use ChangeApiResourceByNamespace; // Optional trait for API resource mapping
    
        // State and methods...
    }
    
  5. Map API Platform to Commands Configure routing in config/packages/api_platform.yaml:

    api_platform:
        formats:
            jsonld:
                mime_types: ['application/ld+json']
        mapping:
            paths: ['%kernel.project_dir%/config/api_resources']
        patch_formats:
            json: ['application/merge-patch+json']
        swagger:
            versions: [3]
    
  6. First Use Case: Create an Event-Driven API Endpoint Define a command and map it to an API Platform operation:

    # config/api_resources/Order.yaml
    resources:
        Order:
            operations:
                create:
                    method: 'POST'
                    mapping:
                        path: '/orders'
                        controller: 'Arnedesmedt\ApiPlatformEventEngineBundle\Controller\CommandController'
                        method: 'createOrder'
                        input: 'App\Command\CreateOrderCommand'
    

Implementation Patterns

Workflow: Event-Driven API Operations

  1. Command Design Implement JsonSchemaAwareRecord and AggregateCommand for commands:

    use Arnedesmedt\EventEngine\Domain\AggregateCommand;
    use Arnedesmedt\EventEngine\Domain\JsonSchemaAwareRecord;
    
    class CreateOrderCommand implements AggregateCommand, JsonSchemaAwareRecord
    {
        use CommandNameAsAggregateMethod; // Auto-maps command to aggregate method
        use JsonSchemaAwareRecordLogic;   // Auto-generates JSON schema
    
        public function __construct(
            public string $customerId,
            public array $items,
        ) {}
    }
    
  2. Aggregate Logic Define aggregate methods to handle commands:

    class Order implements AggregateRoot
    {
        public function createOrder(CreateOrderCommand $command): void
        {
            $this->recordThat(new OrderCreated(
                customerId: $command->customerId,
                items: $command->items,
            ));
        }
    }
    
  3. API Platform Integration Use the CommandController to dispatch commands:

    use Arnedesmedt\ApiPlatformEventEngineBundle\Controller\CommandController;
    
    class OrderController extends CommandController
    {
        public function createOrder(CreateOrderCommand $command): void
        {
            $this->dispatch($command);
        }
    }
    
  4. Query Handling For read operations, use JsonSchemaAwareRecord queries:

    class GetOrderQuery implements JsonSchemaAwareRecord
    {
        use JsonSchemaAwareRecordLogic;
    
        public function __construct(public string $orderId) {}
    }
    

    Map to API Platform:

    resources:
        Order:
            operations:
                get:
                    method: 'GET'
                    mapping:
                        path: '/orders/{id}'
                        controller: 'Arnedesmedt\ApiPlatformEventEngineBundle\Controller\QueryController'
                        method: 'getOrder'
                        input: 'App\Query\GetOrderQuery'
    

Integration Tips

  • Event Sourcing: Leverage EventEngine's event store to replay events for aggregates.
  • Validation: Use JsonSchemaAwareRecord for automatic request validation via OpenAPI.
  • Testing: Use Zenstruck\MessengerTest to mock the command bus in tests:
    $this->bus->expects()
        ->dispatch(new CreateOrderCommand(...))
        ->thenReturn(new Order());
    

Gotchas and Tips

Pitfalls

  1. Aggregate Root Misconfiguration

    • Issue: Forgetting to implement AggregateRoot or ChangeApiResource.
    • Fix: Ensure all aggregates extend AggregateRoot and implement ChangeApiResource (or use the trait).
  2. Command-Operation Mismatch

    • Issue: API Platform operation names not matching aggregate methods.
    • Fix: Use CommandNameAsAggregateMethod trait to auto-map or manually configure in api_resources.yaml:
      operations:
          create:
              method: 'POST'
              mapping:
                  controller: 'App\Controller\OrderController::createOrder'
                  method: 'createOrder' # Must match aggregate method
      
  3. Event Engine Dependency Injection

    • Issue: Missing EventEngine services in Symfony's container.
    • Fix: Ensure arnedesmedt/event-engine-symfony-bundle is properly configured and loaded.
  4. JSON Schema Conflicts

    • Issue: Custom JSON schemas overriding default validation.
    • Fix: Explicitly define schemas in commands/queries:
      class CreateOrderCommand implements JsonSchemaAwareRecord
      {
          public function jsonSchema(): array
          {
              return [
                  'type' => 'object',
                  'properties' => [
                      'customerId' => ['type' => 'string'],
                      'items' => ['type' => 'array'],
                  ],
              ];
          }
      }
      

Debugging Tips

  • Check Event Dispatching Enable debug mode for EventEngine:

    arnedesmedt_event_engine:
        debug: true
    

    Logs will show dispatched commands/events.

  • Validate API Platform Mappings Use bin/console debug:api to verify operation routes and controllers:

    php bin/console debug:api
    
  • Inspect Aggregate State Override AggregateRoot::getState() to log state changes:

    public function getState(): array
    {
        $state = parent::getState();
        error_log('Aggregate state: ' . print_r($state, true));
        return $state;
    }
    

Extension Points

  1. Custom Command Bus Override the default Messenger bus by configuring arnedesmedt_event_engine:

    arnedesmedt_event_engine:
        command_bus: 'custom_bus' # Service ID
    
  2. Event Handlers Extend EventEngine with custom handlers:

    use Arnedesmedt\EventEngine\Domain\EventHandler;
    
    class OrderCreatedHandler implements EventHandler
    {
        public function handle(OrderCreated $event): void
        {
            // Side effects (e.g., send email)
        }
    }
    

    Register in config/packages/arnedesmedt_event_engine.yaml:

    arnedesmedt_event_engine:
        event_handlers:
            App\Event\OrderCreated: ['App\Handler\OrderCreatedHandler']
    
  3. Dynamic API Resource Mapping Use ApiPlatformEventEngineBundle's ResourceMapper to dynamically map operations:

    use Arnedesmedt\ApiPlatformEventEngineBundle\Mapper\ResourceMapper;
    
    $mapper = new ResourceMapper();
    $operations = $mapper->mapResource(Order::class);
    
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.
anousss007/vigilance
supportpal/eloquent-model
ardenexal/fhir-models
laravel-at/laravel-image-sanitize
romalytar/yammi-audit-log-laravel
ardenexal/fhir-validation
arshaviras/weather-widget
laravel-chronicle/core
sunchayn/nimbus
daikazu/eloquent-salesforce-objects
unseen-codes/chat
romalytar/yammi-jobs-monitoring-laravel
kisame76/filament-db-table-state
nqxcode/laravel-lucene-search
dpfx/laravel-livewire-wizards
workos/workos-php-laravel
sofa/laravel-global-scope
nawasara/auth-primitives
adhocrat-io/arkhe-main
make-dev/orca-harpoon