netmex/response
netmex/response is a Laravel package for building HTTP responses with less boilerplate. It provides helpers for JSON replies, status codes, headers, and consistent response formatting, helping controllers stay clean and APIs return predictable output.
Read the README first, and read it as a Symfony doc, not a Laravel one. Netmex Response Bundle is a Symfony bundle: it depends on the Symfony bundle/DI machinery (tagged service discovery, config/bundles.php registration, attribute-driven metadata). There is no Laravel service provider, no facade, no config publish tag in this release.
Minimal steps to evaluate it:
composer require netmex/response in a scratch Symfony app (or a Laravel app only if you intend to hand-wire the container).config/bundles.php.php bin/console debug:container --tag=<strategy tag> (check the README for the exact tag name).#[Response] and hit it.First use case to try: a single read endpoint. Define a DTO with public readonly properties, annotate it with #[Response] (status, headers, and rendering strategy), return it from the controller, and verify the strategy resolver picks the renderer you expect. That exercises the whole loop: controller → DTO → attribute → strategy → HTTP response.
If you are evaluating this as a Laravel developer, the realistic first step is different: skim the DTO + attribute + strategy design and decide whether you want to (a) adopt the package with a custom Laravel service provider that registers and tags the strategies, or (b) borrow the pattern and implement it natively with Laravel's Responsable interface, which already does most of what the controller side of this bundle does.
One DTO per endpoint, named for the response, not the model. The value of the v2 design is that the controller stops knowing about status codes and serialization. Keep the DTO a pure data carrier with readonly properties and put all transport concerns in the #[Response] attribute.
Attribute as the contract. Treat the attribute as the single place where status, headers, and strategy are declared. Resist setting headers imperatively in the controller — the moment you do, you lose the "DTO is the response definition" property that makes the bundle worth using.
Strategy per representation. Register one strategy per output format (JSON envelope, HAL, HTML, CSV, etc.) as a tagged service. The resolver then picks by attribute. This maps cleanly onto a content-negotiation layer: the attribute names a logical strategy, the resolver resolves it, the strategy owns serialization.
Layered controller flow:
Controller → builds DTO → returns DTO
Framework → reads #[Response] → asks resolver → strategy renders AbstractResponse
Keep controllers down to "fetch, map, return". If a controller is doing more than mapping a domain object into a response DTO, the DTO boundary is in the wrong place.
Extending with a custom strategy. Implement the strategy interface (see AbstractResponse and the resolver for the expected contract), register as a service with the documented tag, and let autoconfiguration pick it up. In Symfony this is zero-config if autoconfigure is on; in Laravel you must call $this->app->tag([...], 'netmex.response.strategy') manually.
Laravel integration pattern, if you go that route. Wrap the strategy registration in a package service provider, tag the strategies, bind the resolver as a singleton, and add a middleware or a Responsable-style adapter that intercepts returned DTOs and converts them before the response leaves the controller. Test the adapter path early — this is the part most likely to fight the framework.
2.0.1 explicitly and pin in composer.json; do not rely on a floating constraint while the 2.x line stabilises.#[Response] does when you omit status — 200? 201 for created resources? Verify rather than assume, and be explicit in the attribute for anything non-200.Handler::render), decide which layer wins before you have two competing mappings.debug:container --tag=<tag> to confirm strategies registered, and check autoconfiguration is enabled on your services file. A missing tag produces a "no strategy" error that looks like an attribute problem but isn't.AbstractResponse is the extension point, not the strategy alone. If you need consistent envelope shape (meta, pagination, errors), subclass there rather than duplicating in each strategy.How can I help you explore Laravel packages today?