Weave 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

Responder Bundle Laravel Package

kamyshev/responder-bundle

A Symfony bundle that brings the responder pattern to your applications, converting handler results into HTTP responses and keeping controllers thin. It separates domain logic from response formatting for cleaner, more maintainable PHP code.

View on GitHub
Deep Wiki
Context7

Getting Started

Read this first: kamyshev/responder-bundle is a Symfony bundle, not a Laravel package, and it is effectively unmaintained. Its only recent activity is v1.0.1, whose entire changelog is Replace kamyshev/array_find by kamyshev/array_actions — a transitive dependency rename, not a feature or fix. There is no service provider, no config file to publish, no facade, and no composer.json conflict entry that will protect you from installing it into a Laravel app. For a Laravel codebase the correct first step is still to not install it and read it as a pattern reference, because Laravel's router already implements ~90% of what this bundle does.

If you are inheriting a Symfony 3.x/4.0 app that already uses it, the minimal steps are:

  1. composer require kamyshev/responder-bundle — pin ^1.0.1 if you want the current tree, or the exact old tag if your lockfile depends on kamyshev/array_find. Expect PHP 7.1-era constraints either way.
  2. Register the bundle in app/AppKernel.php (Symfony 3) or config/bundles.php (Symfony 4).
  3. Read the bundle's DependencyInjection/Configuration.php first — that file, not the README, is the source of truth for the responder registration format (a type → service-id map plus a fallback responder).
  4. Find the kernel event listener that swaps the controller's return value for a Response. That listener uses the kamyshev/array_actions helper to resolve a value's type against your map — that lookup is where all your debugging will happen.

First use case: a controller that returns a plain DTO or array instead of new JsonResponse(...), with a single registered responder that serializes anything of that type via the Symfony Serializer. The win is thin controllers and one place to change representation (HTML vs JSON) based on Accept.

The Laravel equivalent you should reach for instead: return an array/Arrayable (auto-JSON), an Illuminate\Http\Resources\Json\JsonResource, or any object implementing Illuminate\Contracts\Support\Responsable. That is the same architectural idea, maintained, and already wired into the framework.

Implementation Patterns

  • Type-dispatch responders. The bundle's model is: controller returns $value; a response listener looks up a responder by the value's class and calls it to produce a Response. In Laravel this maps directly onto Responsable::toResponse($request) — the Router::prepareResponse path already checks for it. If you want the pattern without the dependency, implement Responsable on your DTOs.
  • Keep controllers return-typed on domain objects. Controllers return OrderConfirmation, Collection, array, never Response. In Laravel you can enforce this with a base controller respond() helper or a ResponseFactory macro, which is more honest and greppable than a magic listener.
  • Centralize content negotiation. One responder per media type, chosen from $request->getPreferredFormat(); the Laravel analogue is $request->expectsJson() in a middleware or a single Responder service injected into controllers.
  • Testing split. Unit-test that the controller returns the right value; separately HTTP-test the transform layer. This split is the genuine benefit of the pattern and it survives the migration.
  • Migration tip (Symfony → Laravel). Do not port the listener. Port the shape: a ResponderServiceProvider that binds OrderConfirmation::class to a closure, plus Responsable on the DTOs. Then delete the bundle.
  • If you must stay on Symfony and are upgrading to v1.0.1: the change is a pure dependency swap, so no application code should need to move. Treat it as a lockfile event, not a migration — run the full test suite, confirm the responder map resolves identically, and move on.

Gotchas and Tips

  • v1.0.1 is a dependency rename, not a revival. Do not read the new tag as "actively maintained": the sole change is kamyshev/array_find → kamyshev/array_actions. The bundle is still Symfony-only, still 2018-era PHP constraints, still no Laravel integration.
  • The dependency swap can bite in CI even though it looks inert. If your lockfile pins kamyshev/array_find (or another package requires it), composer update kamyshev/responder-bundle will pull array_actions alongside it and you can end up with both installed, or with a version-constraint conflict if array_actions requires a newer PHP. Diff composer.lock after the bump and check composer why kamyshev/array_actions before assuming nothing changed.
  • The type-map lookup now lives in kamyshev/array_actions. "My responder isn't being called" bugs frequently bottom out in the array-search helper rather than the bundle: first-match-wins ordering, loose vs strict comparison, and how the fallback is appended. Read that package's source, not the bundle README, when resolution misbehaves.
  • Archived = no security patches and no PHP 8 / Symfony 5+ compatibility. Its dependency constraints will block upgrades or resolve to ancient versions. Treat any suggestion to add it as a red flag in review.
  • Interfaces and inheritance are the sharp edge. Type matching is typically exact-class-or-instanceof with an ordered map; the first match wins, so registering a responder for a base class silently swallows all subclasses. Verify ordering in the config, not the docs.
  • Exceptions bypass the responder entirely. Anything thrown before the controller returns never reaches the transform layer, so error payloads are formatted by a different path (Symfony's exception listener). In Laravel this is the Handler + render() — keep both paths consistent or your API returns two different error shapes.
  • Listener ordering is invisible until it breaks. kernel.response ordering relative to Twig/FOSRest/serializer bundles determines whether you get double-encoded JSON or a Response that nobody expected. Debug by logging the event priority, and never dump() and return from a controller that relies on the transform.
  • Responder services must be tagged or public. A private, untagged responder service is the classic silent failure — the fallback responder answers instead and you get a generic 200 instead of your serialized DTO.
  • Config caching masks mistakes. Clear the container cache after changing the type map (and after the v1.0.1 bump); a stale compiled container will keep using the old responder graph.
  • Extension point worth knowing: a catch-all fallback responder (for mixed/scalars) is the only safe place to put "unknown type" logging. If you inherit this code, add one before you touch anything else.
  • Bottom line for a Laravel developer: read it as a 60-line pattern, not a dependency. composer require here buys you an unmaintained Symfony listener you cannot register and should not want — v1.0.1 changes nothing about that.
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.
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names