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

Laravel Transformer Laravel Package

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...

Deep Wiki
Context7

Getting Started

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:

  1. Read README.md for the canonical example — it will be short.
  2. Open 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.
  3. Skim tests/ — for small packages the test suite is usually the most accurate spec of behavior and edge cases.
  4. Check 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.

Implementation Patterns

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.

Gotchas and Tips

  • Tiny community, thin docs. With ~12 stars, expect gaps in the README and no Stack Overflow answers. Pin an exact version in composer.json and be prepared to read src/ when behavior surprises you. Budget time for that.
  • Version support is the first thing to check. A release dated 2025-07-28 is encouraging, but verify the illuminate/* constraints match your Laravel major. A transformer package that lags one Laravel version will be a maintenance tax.
  • Naming collisions. A generic 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.
  • N+1 queries. Transformers are the classic hiding place for lazy-loaded relations. Enforce eager loading at the query layer or add an assertion in tests (Model::preventLazyLoading() in non-production).
  • Type coercion is on you. Most simple transformer packages do not cast or validate; they just shape arrays. Cast explicitly in the transformer ((int), (bool), ISO date strings) so JSON consumers get stable types regardless of database driver.
  • Null safety. Guard optional relations and nullable columns in the transformer; a missing relation turning into null vs. an exception is a decision you should make once, visibly, per transformer.
  • Config and caching. If the package ships a publishable config, publish it (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.
  • Extension points. The base class is usually the extension point — override the mapping method or add protected helpers for shared normalization (money, dates, enums) instead of copy-pasting across transformers. Centralize those helpers early; it's the main thing that keeps a transformer layer from rotting.
  • Escape hatch. Keep transformers free of business logic and side effects. If a transformer starts making queries or dispatching events, it has outgrown the tool — move that logic into an action or query object and let the transformer stay a pure array mapper.

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.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource