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

Fractal Bundle Laravel Package

samj/fractal-bundle

Symfony bundle integrating League\Fractal for transforming API data with transformers, serializers, and includes. Fractal's manager, serializers, and transformers are wired through Symfony's DI container, so you can produce consistent, well-structured JSON responses for your REST API.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the reality check. samj/fractal-bundle is a Symfony 2 bundle, not a Laravel package. It cannot be installed, auto-discovered, or booted in a Laravel app — composer require will fail or the bundle will simply never register (there is no AppKernel, no Bundle class loader). It is archived, last released 2020-06-19, and declares Symfony 2.x constraints that conflict with any modern symfony/* or laravel/framework install.

So there are two "getting started" paths, and you should pick deliberately:

Path A — you are actually on a legacy Symfony 2 project. Then:

  1. composer require samj/fractal-bundle (pin to the 2020 tag; expect conflicts with PHP 8).
  2. Register in app/AppKernel.php: new SamJ\FractalBundle\SamJFractalBundle().
  3. Look first at these three files in the repo:
    • DependencyInjection/ — the extension + config tree (serializer choice, default includes).
    • The compiler pass that collects the transformer service tag — this is the whole point of the bundle.
    • The transformer resolver/factory service — how it maps a model/class to a transformer.
  4. Minimal happy path: define AppBundle\Transformer\UserTransformer as a service, tag it, inject a repository into its constructor, and call the manager from a controller.
// services.yml
app.transformer.user:
    class: AppBundle\Transformer\UserTransformer
    arguments: ['@app.repository.user']
    tags: [{ name: samj_fractal.transformer }]

Path B — you are a Laravel developer evaluating this. Don't use the bundle. Use league/fractal directly (or spatie/laravel-fractal), and steal the one genuinely useful idea: transformers as container-resolved services with constructor injection instead of transformers that app() their dependencies internally.

First use case worth building: a UserTransformer that injects an AvatarUrlGenerator (or a repository) rather than calling a global helper. That single dependency forces you to confront the container wiring, which is the entire value proposition of this package.

Implementation Patterns

1. Transformers as services, resolution by tag. The bundle's contract is "register your transformer, let the container build it." This means the transformer never news up its collaborators:

class UserTransformer extends TransformerAbstract
{
    protected $availableIncludes = ['posts'];

    public function __construct(private AvatarUrlGenerator $avatars) {}

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

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

The problem this instantly exposes: nested transformers (new PostTransformer()) bypass the container. In the bundle you resolve those through the manager too, or inject them. Either way, decide on one convention and enforce it, because mixing container-resolved and new-ed transformers is where teams drift.

2. Container-aware resolver in Laravel. If you are porting the pattern, the equivalent is a small binding plus a resolver that prefers the container:

// AppServiceProvider::register()
$this->app->bind(UserTransformer::class, fn ($app) => new UserTransformer(
    $app->make(AvatarUrlGenerator::class)
));

// A tiny helper the bundle's compiler pass replaces
function transformer(string $class): TransformerAbstract
{
    return app($class);
}

3. Serializer configuration lives in config, not code. The bundle exposes serializer selection (array, JSON-API, data-array). Set it once globally, override per-response only when you genuinely need a different shape. In Laravel the analogue is config/fractal.php or an explicit ->setSerializer(new JsonApiSerializer()) at the manager call site.

4. Controller integration. The typical flow is: fetch models → hand to manager → createData/createDataWithPagination → return. Keep the manager call thin; version negotiation (Accept header, media type) is not provided by the bundle, so if you need API versioning you wire it yourself in a kernel listener or middleware.

5. Includes and eager loading are your responsibility. Fractal's $request->query('include') parsing (parseIncludes) does not eager-load. Pair it with an explicit include→relation map:

$manager->parseIncludes($request->query('include', ''));
$users = User::with($this->includeMap($manager->getRequestedIncludes()))->paginate();

6. Feature-test the transformer, not the bundle. Instantiate the transformer with mocks for its injected collaborators and assert the array shape. The DI design makes this possible — that is the payoff for the wiring overhead.

Gotchas and Tips

  • Archived and Symfony-2-only. No support for Symfony 3+/Flex/autowiring, and the PHP constraint will block PHP 8.x installs. Treat it as a reference implementation, not a dependency. The opportunity score and zero dependents reflect this accurately.
  • The tag name is the API. Most breakage happens because a transformer is registered as a service but not tagged, so it silently falls back to new and loses its injected dependencies — you get an "undefined property" or a null collaborator deep inside transform(), not at wiring time. Verify tags with debug:container --tag=<tag>.
  • Service locator coupling. Resolving transformers from the container inside controllers is fine; resolving collaborators from inside a transformer ($this->get('...')) defeats the purpose and makes the transformer untestable. If you find a container reference inside a transformer, that's the bug.
  • Circular includes. user → posts → author → posts will blow up. Fractal has $maxDepth/recursion guards, but they are per-transformer and easy to forget. Set them deliberately on any bidirectional relationship.
  • Serializer defaults differ from what Laravel folks expect. The default array serializer omits data/meta envelopes; JSON-API adds type and id requirements that your transformer output must satisfy. Pick one at project start — retrofitting a serializer after 30 endpoints exist is a rewrite.
  • includeX return types are strict. Returning a plain array where an Item/Collection is expected fails deep in the manager with a confusing error. Return $this->item(...) / $this->collection(...) always.
  • Performance. Every container-resolved transformer is one more service; a page with 500 records re-resolving transformers can be measurably slower than a cached array. Cache the transformed payload for expensive serializers.
  • Extension point: the compiler pass that collects tagged transformers is the single place to customize resolution (aliasing model→transformer, default includes per type). If you port this pattern to Laravel, that map is the piece worth reimplementing — it is genuinely better than spatie/laravel-fractal's convention-only resolution when transformers have real dependencies.
  • Debugging tip: because the bundle is unmaintained, isolate it behind a thin interface in your own code so a future swap to league/fractal directly (or to Symfony's built-in serializer) is a one-file change rather than a hunt-and-replace.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource