sroze/api-platform-messenger
Integrates Symfony Messenger with API Platform so create, update, and delete operations are dispatched as messages to a bus instead of handled inline. Route resource persistence through message handlers, run writes asynchronously, and keep your API resources thin with clean, CQRS-style separation.
Install the package alongside its two hard dependencies:
composer require sroze/api-platform-messenger
You need a working Symfony app with symfony/messenger and api-platform/core already configured (a messenger.yaml with at least one bus, and API Platform exposing resources).
Look first at the package's README.md, tests/, and any example/ or docs/ folder. This is a small (31★) package, so the tests are the most reliable specification you'll find. Pay attention to how the package registers its API Platform data provider / data persister (or operation) — that's the integration point you'll be depending on.
Register the bundle if the package ships one (check vendor/sroze/api-platform-messenger/src/*Bundle.php). If there's no bundle, look for a compiler pass or a service you must alias manually.
Verify the wiring with:
bin/console debug:router
bin/console debug:messenger
You should see your message classes appear as routes, and the handler should be attached to the right bus.
First use case — replace a hand-written controller with a message. The canonical pattern is a CreateBook command exposed as POST /books:
#[ApiResource(
operations: [new Post()],
messenger: true, // or the package-specific attribute/annotation
)]
final class CreateBook
{
public string $title;
}
You dispatch nothing yourself — API Platform deserializes the request body into CreateBook, the package pushes it onto the bus, and your CreateBookHandler does the work. Return a DTO (or null) and the package turns it into the response.
CreateBook, UpdateBook, DeleteBook as commands; GetBook, ListBooks as queries. This mirrors the CQRS split the package is designed around and keeps routing predictable.command.bus and query.bus in messenger.yaml and let the package's attribute/annotation pick the bus. This is where the package pays off — you can enforce "queries are synchronous, commands are async" purely in config.#[Assert\NotBlank], #[Assert\Length]) directly on the message properties — API Platform will run the validator before the bus dispatch.void/null typically becomes 204 No Content.ExceptionListener/kernel.exception subscriber to convert it to the right status code (404 for BookNotFound, 422 for validation, etc.). Don't try to catch exceptions inside the handler — that's not where HTTP lives.#[IsGranted] or an API Platform security string on the resource operation; the package doesn't replace Symfony Security. Voters keyed on the message class work well.async) and read buses in-memory. A query must return synchronously or the response is empty — never route queries through an async transport.KernelBrowser against the generated routes — same as testing any API Platform resource.DataProvider/DataPersister interfaces changed signatures). Expect to either pin api-platform/core:^2.x or patch the package's integration classes. Check the composer.json constraints before you commit.vendor/sroze/api-platform-messenger/src for Attribute classes and use what's actually there.void and use 202 Accepted semantics; use sync queries for anything you want to read back.input/output groups or a distinct response DTO returned by the handler — otherwise you leak internal fields or fail to expose computed ones.bin/console messenger:failed:show and messenger:failed:retry. In dev, enable the Messenger data collector in the profiler; it shows the exact message dispatched, the bus, and handler failures. Combine with debug:router to confirm the operation was actually registered.routePrefix/operation name explicit on each message, and check debug:router after adding a new one.POST /your-resource reaches the handler — that test is your early-warning system for upgrades.How can I help you explore Laravel packages today?