gnugat/marshaller-bundle
Symfony bundle that integrates the gnugat/marshaller library, providing service configuration and dependency injection for marshalling and unmarshalling data between PHP objects and arrays or other representations. Useful for cleanly separating transformation logic in Symfony applications.
This is the initial v1.0.0 release, so treat everything below as the baseline. The package wires gnugat/marshaller v1.0 into Laravel's service container under the service id gnugat_marshaller.marshaller and registers the marshaller with the gnugat_marshaller container tag.
Install it and confirm the provider is registered:
composer require gnugat/marshaller-laravel # check the actual composer name in the release
If the package is not auto-discovered, add its provider to config/app.php (Laravel <11) or bootstrap/providers.php. Publish any config with php artisan vendor:publish --tag=gnugat_marshaller if the package ships one.
Look first at:
config/gnugat_marshaller.php (if published) — it defines which marshallers resolvers are wired up.gnugat_marshaller.marshaller and the gnugat_marshaller tag are populated.Gnugat\Marshaller\Marshaller interface in vendor/gnugat/marshaller — this is the contract you'll depend on.First use case — resolve the marshaller and marshal a payload:
use Gnugat\Marshaller\Marshaller;
$marshaller = app('gnugat_marshaller.marshaller');
$result = $marshaller->marshal($data);
If your resolvers are configured for type-based dispatch, this converts incoming arrays/objects into your target representation (e.g. DTO -> array for JSON responses, or array -> DTO in request handling).
Constructor injection (preferred over app()). Inject the marshaller via its interface so you stay testable:
use Gnugat\Marshaller\Marshaller;
final class ExportOrders
{
public function __construct(private Marshaller $marshaller) {}
public function __invoke(array $orders): array
{
return array_map(fn ($o) => $this->marshaller->marshal($o), $orders);
}
}
Laravel will autowire the tagged/resolved binding if the container is configured to alias the interface to gnugat_marshaller.marshaller.
Consume the gnugat_marshaller tag for aggregation. The tag exists precisely so you can collect every configured marshaller (e.g. to build a resolver or a pipeline):
$marshallers = iterator_to_array(app()->tagged('gnugat_marshaller'));
Use this when you want to iterate candidate marshallers, inspect them for debugging, or build your own composite resolver.
Register custom marshallers by implementing the package's Marshaller interface and tagging them in your own service provider:
$this->app->tag([OrderMarshaller::class], 'gnugat_marshaller');
Keep custom marshallers stateless — they're effectively singletons (see Gotchas).
Integrate at the boundaries, not deep in your domain. Good seams:
Because gnugat/marshaller resolves which marshaller to use via a Resolver, the day-to-day workflow is: define a marshaller per shape, register it, and let the resolver pick based on type. Keep resolver priority/type maps in config so you can reorder without touching code.
gnugat_marshaller.marshaller is registered as a shared instance. Any stateful marshaller you tag will leak state across requests in long-running workers (Octane, queues). Make marshallers pure and immutable.gnugat_marshaller.marshaller is the resolved marshaller; gnugat_marshaller is the tag used for collection. Don't confuse them — app('gnugat_marshaller') won't do what you expect; use app()->tagged('gnugat_marshaller').php artisan config:cache in deploy. A stale config cache is the usual reason a newly tagged marshaller "isn't picked up."gnugat/marshaller dispatches to the first resolver/marshaller that supports the data. If two custom marshallers both claim array, the first registered wins — order your tags or type map deliberately and write a test that asserts precedence.app()->tagged('gnugat_marshaller') and inspect each marshaller's supports() logic — the resolver is almost always the culprit, not the marshaller body.Resolver/Marshaller and tagging it over decorating gnugat_marshaller.marshaller in a service provider — decorators on the named service are fragile if the package rebinds it in a later minor version.gnugat/marshaller at v1.0; check its changelog before bumping, as the resolver/marshaller contracts are the fragile part of the integration.How can I help you explore Laravel packages today?