konsulting/laravel-transformer
A Laravel package for transforming data structures and API responses through dedicated transformer classes. It helps keep controllers and models clean by centralizing reusable transformation logic, making it easy to shape arrays, Eloquent models, and collections into consistent output for JSON respo...
Install it like any other Laravel package:
composer require konsulting/laravel-transformer
Because the package has a small footprint and a tiny audience (12 stars), treat the source and tests as the primary documentation. Before writing code, in this order:
README.md for the canonical example — it will be short.src/ and look for the base Transformer class/contract and any service provider. That tells you the actual method signature (transform(), __invoke(), handle(), etc.) rather than guessing.tests/ — for small packages the test suite is usually the most accurate spec of behavior and edge cases.composer.json for the supported Laravel/PHP ranges before committing to it in a project.A reasonable first use case: you have an Eloquent model and need a stable array shape for an API response, an export, or a queued job payload. Create one transformer per output shape:
namespace App\Transformers;
use App\Models\Order;
use Konsulting\Transformer\Transformer; // verify exact FQCN from src/
class OrderTransformer extends Transformer
{
public function transform(Order $order): array
{
return [
'id' => $order->id,
'reference' => $order->reference,
'total' => (int) $order->total_cents,
'placed_at' => $order->placed_at?->toIso8601String(),
];
}
}
Then call it wherever the array is needed. Keep the first implementation deliberately boring: one transformer, one model, no nesting. Expand only once you've confirmed the package's calling convention against its tests.
Transformers as explicit output contracts. The value of this package is that transformation lives in a named class instead of an ad-hoc toArray() override. Wire it into controllers rather than sprinkling array building through the app:
public function show(Order $order, OrderTransformer $transformer)
{
return response()->json($transformer->transform($order));
}
Constructor injection works if the package registers transformers in the container; if not, resolve manually or instantiate directly. Confirm from the service provider.
Collections and pagination. Transforming a single model is trivial; the day-to-day work is lists. Wrap the paginator so metadata survives:
$orders = Order::query()->paginate();
return response()->json([
'data' => $orders->getCollection()->map(fn ($o) => $transformer->transform($o)),
'meta' => [
'current_page' => $orders->currentPage(),
'total' => $orders->total(),
],
]);
If the package ships a collection helper, prefer it — but verify it preserves keys and pagination metadata, which is where most homegrown transformer helpers break.
Composition over inheritance for nesting. Compose small transformers rather than building deep inheritance chains:
class OrderWithCustomerTransformer extends Transformer
{
public function __construct(private CustomerTransformer $customers) {}
public function transform(Order $order): array
{
return [
...(new OrderTransformer)->transform($order),
'customer' => $this->customers->transform($order->customer),
];
}
}
Eager-load relationships in the query (->with('customer')) before transforming — the transformer should not trigger lazy loads.
Input transformation, not just output. The same pattern is useful for normalizing request payloads before validation or persistence (trimming, casting, mapping external field names to internal ones). Run the transformer in a form request's prepareForValidation() or a dedicated action class, then validate the normalized array.
Testing transformers directly. Because a transformer is a pure-ish class, test it without HTTP: instantiate it with a model (or plain array) and assert the exact array shape with assertSame. This is the highest-leverage test you can write and it protects downstream consumers of the shape.
Where it fits versus the framework. Laravel API Resources, spatie/laravel-data, and league/fractal all overlap heavily with this package. Use this one when you want a lightweight, hand-written array mapper without resource classes or DTO hydratation. Do not layer it on top of API Resources — pick one mechanism per boundary.
composer.json and be prepared to read src/ when behavior surprises you. Budget time for that.illuminate/* constraints match your Laravel major. A transformer package that lags one Laravel version will be a maintenance tax.transform() method can clash with framework helpers and queue/serialization internals. Keep transformer calls explicit ($transformer->transform($model)) and avoid relying on magic __invoke if you also pass transformers as callables to map() — the argument order matters.Model::preventLazyLoading() in non-production).(int), (bool), ISO date strings) so JSON consumers get stable types regardless of database driver.null vs. an exception is a decision you should make once, visibly, per transformer.php artisan vendor:publish) rather than editing vendor files, and remember config caching in production will freeze it. Check whether a service provider is auto-discovered or must be registered.Overall: a small, low-ceremony utility that is a good fit for teams that want explicit, testable output mapping without adopting a larger DTO or resource framework. Its main risk is not technical but ecosystem — low adoption means you own the debugging and upgrade path.
How can I help you explore Laravel packages today?