Weave Code
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

dmytrof/fractal-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install & Enable

    composer require dmytrof/fractal-bundle
    

    Register in config/bundles.php (Symfony 4/5) or AppKernel.php (Symfony 3):

    Dmytrof\FractalBundle\DmytrofFractalBundle::class => ['all' => true],
    
  2. Configure Fractal Add to config/packages/fractal.yaml (Symfony 4/5) or app/config/config.yml (Symfony 3):

    fractal:
        default_format: 'jsonapi' # or 'hal', 'rest'
        default_includes: ['author'] # optional
    
  3. First Transformation Inject FractalManager into a controller/service:

    use Dmytrof\FractalBundle\Manager\FractalManager;
    
    public function __construct(private FractalManager $fractalManager) {}
    
    public function showArticle(Article $article): JsonResponse
    {
        $transformer = new ArticleTransformer();
        $resource = new Item($article, $transformer);
    
        return $this->fractalManager->createResponse($resource);
    }
    
  4. Key Files to Review

    • config/packages/fractal.yaml (or config.yml)
    • src/Transformer/ (custom transformers)
    • src/Service/ (custom manager extensions)

Implementation Patterns

Core Workflow: Data → Transformer → Response

  1. Model → Transformer Create a transformer for your entity (e.g., ArticleTransformer):

    class ArticleTransformer extends AbstractTransformer
    {
        public function transform(Article $article)
        {
            return [
                'id' => $article->getId(),
                'title' => $article->getTitle(),
                'published_at' => $article->getPublishedAt()->format('Y-m-d'),
            ];
        }
    
        public function includeAuthor(Article $article)
        {
            return $this->item($article->getAuthor(), new AuthorTransformer());
        }
    }
    
  2. Resource Creation Use Item (single) or Collection (multiple) resources:

    $resource = new Item($article, new ArticleTransformer());
    // OR for collections:
    $resource = new Collection($articles, new ArticleTransformer());
    
  3. Response Handling Leverage the bundle’s FractalManager for consistent responses:

    $response = $this->fractalManager->createResponse($resource, 200, [], [
        'include' => ['author'], // eager-load includes
        'exclude' => ['body'],   // exclude fields
    ]);
    
  4. API Versioning Override the manager per version:

    # config/packages/fractal_v1.yaml
    fractal:
        default_format: 'jsonapi'
        default_includes: ['author']
    
    // In a controller
    $this->fractalManager->setFormat('hal'); // Override per request
    

Integration Tips

  1. Symfony Serializer Integration Use Fractal’s DataArray with Symfony’s Serializer for hybrid APIs:

    use League\Fractal\Serializer\DataArraySerializer;
    
    $serializer = new DataArraySerializer();
    $this->fractalManager->setSerializer($serializer);
    
  2. Event Listeners Attach listeners to modify responses globally:

    // src/EventListener/FractalListener.php
    public function onKernelResponse(GetResponseForControllerResultEvent $event)
    {
        $result = $event->getControllerResult();
        if ($result instanceof Item) {
            $event->setResponse($this->fractalManager->createResponse($result));
        }
    }
    
  3. Custom Error Handling Extend the manager to handle exceptions:

    $this->fractalManager->addErrorHandler(function (Throwable $e) {
        return new ErrorResponse($e->getMessage(), 500);
    });
    
  4. Testing Mock FractalManager in tests:

    $fractalManager = $this->createMock(FractalManager::class);
    $fractalManager->method('createResponse')->willReturn(new JsonResponse([]));
    $this->app->instance(FractalManager::class, $fractalManager);
    

Gotchas and Tips

Pitfalls

  1. Format Mismatches

    • Issue: Using jsonapi format but sending hal headers.
    • Fix: Explicitly set the format in the manager:
      $this->fractalManager->setFormat('hal');
      
  2. Circular References

    • Issue: Transformers with circular dependencies (e.g., UserPost).
    • Fix: Use include paths carefully or implement lazy-loading:
      public function includePosts(User $user)
      {
          return $this->collection($user->getPosts(), new PostTransformer(), 'posts');
      }
      
  3. Deprecated Symfony Versions

    • The bundle was last updated in 2021 for Symfony 5.1. Test thoroughly on newer versions (e.g., Symfony 6+ may require adjustments).
  4. Configuration Overrides

    • Issue: Bundle config in config/packages/ is ignored if not loaded.
    • Fix: Ensure the bundle is enabled before other bundles that might override configs.

Debugging Tips

  1. Inspect Transformed Data Use Fractal’s DataArray serializer to debug output:

    $serializer = new DataArraySerializer();
    $this->fractalManager->setSerializer($serializer);
    // Response will now show raw arrays for inspection.
    
  2. Enable Fractal Logging Add to config/packages/monolog.yaml:

    handlers:
        fractal:
            type: stream
            path: "%kernel.logs_dir%/fractal.log"
            level: debug
    

    Then enable logging in the manager:

    $this->fractalManager->setLogger($this->container->get('logger'));
    
  3. Common Errors

    • "Transformer not found": Ensure the transformer class is autoloaded and namespaced correctly.
    • "Invalid format": Verify the format (e.g., jsonapi, hal) is supported by the installed league/fractal version.

Extension Points

  1. Custom Serializers Replace the default serializer:

    $this->fractalManager->setSerializer(new CustomSerializer());
    
  2. Dynamic Transformer Selection Use a factory to resolve transformers dynamically:

    $transformer = $this->transformerFactory->create($entity->getClass());
    
  3. Middleware Integration Add Fractal-specific middleware for request/response manipulation:

    // src/Middleware/FractalMiddleware.php
    public function handle(Request $request, Closure $next)
    {
        $response = $next($request);
        if ($response instanceof JsonResponse) {
            $response->headers->set('X-Data-Format', 'jsonapi');
        }
        return $response;
    }
    
  4. Database Abstraction Combine with Doctrine for ORM-aware transformers:

    use Doctrine\ORM\EntityManagerInterface;
    
    public function __construct(private EntityManagerInterface $em) {}
    
    public function transform(Article $article)
    {
        $this->em->refresh($article); // Ensure fresh data
        return [...];
    }
    
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui