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

Transformers Laravel Package

saritasa/transformers

Saritasa Transformers is a Laravel package for turning models and data structures into consistent arrays or JSON using reusable transformer classes. It keeps API output, nested relationships, and custom formatting organized and easy to maintain.

View on GitHub
Deep Wiki
Context7

Getting Started

composer require saritasa/transformers
php artisan vendor:publish --provider="Saritasa\Transformers\TransformersServiceProvider" 2>/dev/null || true

Read these first, in order:

  1. composer.json — confirms it depends on league/fractal and the Laravel version it was written against (the 2024-08 release likely targets Laravel 10/11, PHP 8.1+).
  2. src/ — the package is thin. Expect a base transformer class (e.g. BaseTransformer), a Transformable trait for Eloquent models, and a service provider that binds a Fractal manager.
  3. tests/ — the fast path to understanding intended usage, since the README of a 1-star archived package is often incomplete.
  4. League/Fractal docs (https://fractal.thephpleague.com) — this package is a convention layer, so all real behavior lives in Fractal. Anything you can't find in src/ is a Fractal concept.

First use case — expose a model as a JSON payload:

class UserTransformer extends \Saritasa\Transformers\BaseTransformer // or TransformerAbstract
{
    protected $availableIncludes = ['posts'];

    public function transform(User $user): array
    {
        return [
            'id'    => (int) $user->id,
            'name'  => $user->name,
            'email' => $user->email,
        ];
    }

    public function includePosts(User $user)
    {
        return $this->collection($user->posts, new PostTransformer());
    }
}

// In a controller:
return response()->json(
    fractal()->item($user, new UserTransformer())->toArray()
);

If the service provider doesn't auto-register on your Laravel version, add Saritasa\Transformers\TransformersServiceProvider::class to config/app.php. If it's not bound at all, fall back to new \League\Fractal\Manager() — the package's value is the transformer conventions, not the plumbing.

Implementation Patterns

Base transformer inheritance. The usual Saritasa pattern is a BaseTransformer that pre-wires defaults (serializer, recursion depth, common fields like id/timestamps). Extend it, keep every transform() returning an explicit scalar array — never $model->toArray() — or you lose the whole point of the layer.

Relationships via includes, not nested transforms. Declare in $availableIncludes / $defaultIncludes and implement includeXxx(). Callers opt in with ?include=posts,posts.comments. This keeps payloads sparse by default and prevents accidental deep serialization.

Collection + pagination. For lists:

$resource = fractal()
    ->collection($users, new UserTransformer())
    ->paginateWith(new \League\Fractal\Pagination\IlluminatePaginatorAdapter($users))
    ->parseIncludes($request->input('include', ''));

Always chain ->parseIncludes() when includes are user-driven; otherwise the client's ?include= is silently ignored and you'll chase a phantom bug.

Serializer choice is a per-manager decision. Pick once. ArraySerializer gives plain arrays (most REST APIs); JsonApiSerializer gives data/relationships/included shapes. Swapping serializers mid-project breaks client contracts and every test that asserts on the shape.

DTOs and view models. Don't reserve transformers for Eloquent. Transformers are the right tool for arrays, stdClass, or API-response DTOs — anywhere you need to freeze a response contract.

Testing. Test transformers directly rather than through HTTP:

$payload = (new Manager())->createData(new UserTransformer()::$user ?? null) // see gotcha below

In practice: instantiate the manager, setSerializer(new ArraySerializer()), wrap ->item($model, new UserTransformer())->toArray(), and assert against a fixture. This isolates transformer regressions from routing/controller noise.

Custom resolvers. If you have many transformers, register a resolver on the manager so $this->item($post, new PostTransformer()) inside an include collapses into $this->item($post, PostTransformer::class). Worth the ten lines on any nontrivial API.

Gotchas and Tips

  • The package is archived. Last release Aug 2024, 1 star, 0 dependents. Pin the exact version, vendor it into app/Support/ if you need changes, and treat it as a reference implementation rather than a maintained dependency. If Fractal itself moves, this package won't follow. For a new project, consider depending on league/fractal directly and copying the conventions.
  • N+1 queries. Includes are resolved lazily. Eager-load on the query (User::with('posts')) before handing the model to Fractal; the transformer can't see your query builder. defaultIncludes are the most common source of surprise N+1s.
  • $this->item() vs $this->collection() vs $this->null(). Return the null resource explicitly when a relation is absent — returning null or [] from an includeXxx method produces inconsistent shapes across serializers.
  • Serializer vs toArray()/toJson(). toArray() on a resource still goes through the serializer; toJson() and toArray() differ in how meta/links render for some serializers. Assert with the same method the controller uses.
  • Recursion depth. Fractal defaults to a recursion limit; deeply nested self-referential includes (user → posts → author → posts) will stop at the limit and give you null in the response with no error. Raise setRecursionLimit() deliberately, not blindly.
  • parseIncludes() before toArray(). Order matters — the includes must be parsed on the resource before serialization. If you see all-null relationships, this is usually why.
  • Fractal version pin. Ensure league/fractal isn't also pulled in transitively at a conflicting constraint by spatie/laravel-fractal or similar. One manager, one serializer — mixing managers is a classic source of "why is data double-wrapped?".
  • Debugging. Dump the raw transformer output by calling transform() directly, then dump the resource after ->toArray(). That isolates "my transformer is wrong" from "my serializer is wrong."
  • Extension points worth using: a custom BaseTransformer (timestamps/IDs/nulls), a custom IncludeResolver (auto-resolve transformer classes by convention), a custom Serializer if you need a house response envelope, and a Transformable trait that adds ->transform() to models for convenience.
  • Config quirks. If a config/transformers.php is published, expect keys for the default serializer, default includes, and recursion limit. Change them in AppServiceProvider::boot() rather than in the controller so behavior is consistent across the app.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle