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

Elytus Limoncello Bundle Laravel Package

drewclauson/elytus-limoncello-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require drewclauson/elytus-limoncello-bundle
    

    Add to config/bundles.php (Symfony 4+):

    Drewclauson\ElytusLimoncelloBundle\ElytusLimoncelloBundle::class => ['all' => true],
    
  2. Configuration: Override default settings in config/packages/elytus_limoncello.yaml:

    elytus_limoncello:
        serializer: 'App\Serializer\CustomJsonApiSerializer'
        resource_classes: ['App\Resource\*']
    
  3. First Use Case: Create a JSON:API resource (e.g., app/Resource/PostResource.php):

    namespace App\Resource;
    
    use Limoncello\Resource\AbstractResource;
    
    class PostResource extends AbstractResource
    {
        public function getType()
        {
            return 'posts';
        }
    
        public function getId($model)
        {
            return $model->id;
        }
    
        public function getAttributes($model)
        {
            return [
                'title' => $model->title,
                'body' => $model->body,
            ];
        }
    }
    
  4. Routing: Define a route in routes/api.php:

    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;
    
    $router->get('/posts', function (Request $request) {
        $posts = Post::all();
        return new Response(
            $this->get('elytus_limoncello.serializer')->serialize($posts, 'posts'),
            Response::HTTP_OK,
            ['Content-Type' => 'application/vnd.api+json']
        );
    });
    

Implementation Patterns

Core Workflows

  1. Resource-Based Serialization:

    • Group related models under a single resource type (e.g., posts, users).
    • Extend AbstractResource for custom logic (e.g., filtering, sorting, or nested relationships).
    • Example:
      public function getRelationships($model)
      {
          return [
              'author' => new AuthorResource($model->author),
          ];
      }
      
  2. Request Handling:

    • Parse JSON:API requests (e.g., filtering, pagination, sparse fieldsets) via Limoncello\Request\Request.
    • Inject into controllers:
      public function index(Request $request)
      {
          $request = $this->get('elytus_limoncello.request_factory')->createFromGlobals();
          $posts = Post::query()->filter($request)->paginate();
          return $this->serialize($posts, 'posts');
      }
      
  3. Pagination:

    • Use Limoncello\Pagination\CursorPagination or PagePagination:
      # config/packages/elytus_limoncello.yaml
      elytus_limoncello:
          pagination: 'cursor'
      
  4. Error Handling:

    • Customize error responses via Limoncello\Error\ErrorHandler:
      $this->get('elytus_limoncello.error_handler')->setRenderer(function ($error) {
          return new Response(json_encode($error), 400);
      });
      

Integration Tips

  • Symfony Forms: Use Symfony\Component\Form\FormFactory alongside Limoncello for input validation. Example:

    $form = $this->createForm(PostType::class, $post);
    if ($form->isSubmitted() && $form->isValid()) {
        $post = $form->getData();
        $this->serialize($post, 'posts', 'create');
    }
    
  • Doctrine ORM: Leverage Doctrine’s Repository methods for complex queries:

    public function getAttributes($model)
    {
        return [
            'comments_count' => $model->getComments()->count(),
        ];
    }
    
  • API Versioning: Use Symfony’s api_platform or api route prefixing:

    # config/routes/api_v1.yaml
    api_v1_posts:
        path: /api/v1/posts
        controller: App\Controller\PostController::index
    

Gotchas and Tips

Pitfalls

  1. Outdated Dependencies:

    • The package was last updated in 2015 and relies on older versions of Limoncello (~1.0).
    • Workaround: Fork and update dependencies (e.g., neomerx/json-api:^2.0) or use neomerx/limoncello-bundle as a drop-in alternative.
  2. Missing Documentation:

  3. Service Container Conflicts:

    • The bundle assumes specific service IDs (e.g., elytus_limoncello.serializer). Override in services.yaml if needed:
      services:
          App\Serializer\CustomSerializer:
              tags: ['elytus_limoncello.serializer']
      
  4. Caching Headers:

    • Limoncello doesn’t auto-generate ETag or Last-Modified. Add manually:
      $response->setEtag(md5($serializedData));
      $response->isNotModified($request);
      

Debugging Tips

  1. Request Inspection: Dump the parsed request object:

    $request = $this->get('elytus_limoncello.request_factory')->createFromGlobals();
    dump($request->all());
    
  2. Serialization Debugging: Check raw output before JSON encoding:

    $data = $this->get('elytus_limoncello.serializer')->serialize($model, 'posts');
    file_put_contents('debug.json', json_encode($data, JSON_PRETTY_PRINT));
    
  3. Common Errors:

    • ResourceNotFoundException: Verify getType() and getId() in your resource class.
    • InvalidArgumentException: Ensure model data matches expected attributes/relationships.

Extension Points

  1. Custom Serializers: Extend Limoncello\Serializer\Serializer for non-standard JSON:API behavior:

    class CustomSerializer extends \Limoncello\Serializer\Serializer
    {
        protected function createMeta(array $meta)
        {
            $meta['custom_field'] = 'value';
            return parent::createMeta($meta);
        }
    }
    

    Register in services.yaml:

    elytus_limoncello.serializer: '@App\Serializer\CustomSerializer'
    
  2. Middleware: Add Limoncello-specific middleware (e.g., CORS, auth) via Symfony’s kernel.middleware:

    framework:
        middleware:
            elytus_limoncello.cors:
                before: [symfony.web_link_formatter]
    
  3. Event Listeners: Hook into Limoncello’s lifecycle (e.g., pre-serialize):

    $dispatcher->addListener(
        'elytus_limoncello.pre_serialize',
        function ($event) {
            $event->getData()->add('custom_meta', 'value');
        }
    );
    
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.
nasirkhan/laravel-sharekit
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony