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

Rest Extra Bundle Laravel Package

willdurand/rest-extra-bundle

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**
   Add the bundle to your `composer.json`:
   ```bash
   composer require willdurand/rest-extra-bundle

Enable it in config/bundles.php:

return [
    // ...
    Bazinga\RestExtraBundle\BazingaRestExtraBundle::class => ['all' => true],
];
  1. First Use Case: API Resource Transformation Define a serializer for your entity (e.g., User) in src/Serializer/UserSerializer.php:

    namespace App\Serializer;
    
    use Bazinga\RestExtraBundle\Serializer\SerializerAwareInterface;
    use Bazinga\RestExtraBundle\Serializer\SerializerAwareTrait;
    use Bazinga\RestExtraBundle\Serializer\SerializerBuilderInterface;
    use Bazinga\RestExtraBundle\Serializer\SerializerContextBuilderInterface;
    
    class UserSerializer implements SerializerAwareInterface
    {
        use SerializerAwareTrait;
    
        public function serialize($user, $format, array $context = [])
        {
            return [
                'id' => $user->getId(),
                'name' => $user->getName(),
                'email' => $user->getEmail(),
            ];
        }
    }
    
  2. Register the Serializer Configure the bundle in config/packages/bazinga_rest_extra.yaml:

    bazinga_rest_extra:
        serializers:
            App\Entity\User: App\Serializer\UserSerializer
    
  3. Test the API Use the built-in Serializer service to transform data:

    $user = $this->getDoctrine()->getRepository(User::class)->find(1);
    $serializer = $this->get('bazinga.rest.serializer');
    $data = $serializer->serialize($user, 'json');
    

Implementation Patterns

1. Serializer Workflows

  • Custom Serialization Logic Extend Bazinga\RestExtraBundle\Serializer\SerializerAwareTrait to leverage the bundle’s built-in serializer. Example: Filter sensitive fields dynamically:

    public function serialize($user, $format, array $context = [])
    {
        $data = [
            'id' => $user->getId(),
            'name' => $user->getName(),
        ];
    
        if (isset($context['include_email']) && $context['include_email']) {
            $data['email'] = $user->getEmail();
        }
    
        return $data;
    }
    
  • Context-Based Serialization Pass context via API requests (e.g., ?include=email) and access it in serializers:

    # config/routes.yaml
    app_user:
        path: /users/{id}
        methods: GET
        defaults:
            _controller: App\Controller\UserController::getUser
            _serializer_context: { include_email: true }
    
  • Nested Resource Serialization Use SerializerBuilderInterface to handle relationships:

    $builder = $this->get('bazinga.rest.serializer.builder');
    $builder->add('user.posts', 'App\Serializer\PostSerializer');
    $serialized = $builder->build($user)->serialize($user, 'json');
    

2. Validation Integration

  • Form Validation for APIs Use the bundle’s Validator service to validate incoming data:

    use Bazinga\RestExtraBundle\Validator\ValidatorInterface;
    
    public function createUser(ValidatorInterface $validator, Request $request)
    {
        $data = json_decode($request->getContent(), true);
        $errors = $validator->validate($data, 'App\Entity\User');
    
        if (count($errors) > 0) {
            return $this->json($errors, 400);
        }
    
        // Proceed with creation
    }
    
  • Custom Validation Groups Define groups in your entity (e.g., User.php):

    use Symfony\Component\Validator\Constraints as Assert;
    
    class User
    {
        /**
         * @Assert\NotBlank(groups={"create"})
         */
        private $name;
    }
    

    Use groups in validation:

    $validator->validate($data, 'App\Entity\User', ['groups' => ['create']]);
    

3. Event-Driven Extensions

  • Pre/Post Serialization Events Subscribe to events to modify serialization dynamically:

    use Bazinga\RestExtraBundle\Event\PreSerializeEvent;
    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    
    class UserSerializerSubscriber implements EventSubscriberInterface
    {
        public static function getSubscribedEvents()
        {
            return [
                'bazinga_rest.pre_serialize' => 'onPreSerialize',
            ];
        }
    
        public function onPreSerialize(PreSerializeEvent $event)
        {
            $data = $event->getData();
            if ($event->getObject() instanceof User) {
                $data['custom_field'] = 'dynamic_value';
                $event->setData($data);
            }
        }
    }
    
  • Custom Serializer Formats Register new formats (e.g., hal+json) in config:

    bazinga_rest_extra:
        formats:
            hal+json: ['json']
    

4. Performance Optimizations

  • Caching Serialized Output Use Symfony’s cache system to cache serialized responses:

    # config/packages/bazinga_rest_extra.yaml
    bazinga_rest_extra:
        serializer:
            cache: true
            cache_pool: app.cache.serializer
    
  • Batch Processing Serialize collections efficiently:

    $users = $this->getDoctrine()->getRepository(User::class)->findAll();
    $serializer = $this->get('bazinga.rest.serializer');
    $data = $serializer->serialize($users, 'json', ['collection' => true]);
    

Gotchas and Tips

Common Pitfalls

  1. Serializer Registration Order

    • Issue: Serializers may not be picked up if registered after the bundle’s compiler pass.
    • Fix: Ensure App\Serializer\UserSerializer is autowired or manually registered in services.yaml:
      services:
          App\Serializer\UserSerializer:
              tags: ['bazinga_rest.serializer']
      
  2. Circular References

    • Issue: Serializing nested entities with circular references (e.g., User->posts->author->posts) causes infinite loops.
    • Fix: Use SerializerBuilderInterface to limit depth or implement custom logic:
      $builder->add('user.posts', 'App\Serializer\PostSerializer', ['max_depth' => 1]);
      
  3. Validation Overhead

    • Issue: Validating large payloads can slow down API responses.
    • Fix: Use partial validation or async validation (e.g., Symfony Messenger).
  4. Deprecated Symfony 2/3 Features

    • Issue: The bundle is designed for Symfony 2/3 and may not work out-of-the-box with Symfony 4/5.
    • Fix: Override bundle services in config/services.yaml or use a compatibility layer like symfony/flex.
  5. Context Propagation

    • Issue: Context passed in routes may not propagate to nested serializers.
    • Fix: Merge context manually in serializers:
      $context = array_merge($context, ['parent_key' => 'value']);
      

Debugging Tips

  1. Enable Verbose Serialization

    • Pass debug: true in context to log serialization steps:
      $serializer->serialize($user, 'json', ['debug' => true]);
      
  2. Check Serializer Groups

    • Ensure your entity’s validation groups match the groups passed to the validator:
      $validator->validate($data, User::class, ['groups' => ['Default', 'create']]);
      
  3. Inspect Events

    • Dump events to debug pre/post serialization:
      $event->getData(); // Inspect input data
      $event->getObject(); // Inspect the original object
      

Extension Points

  1. Custom Serializer Awareness

    • Implement SerializerAwareInterface to access the serializer instance within your serializer:
      use Bazinga\RestExtraBundle\Serializer\SerializerAwareInterface;
      
      class CustomSerializer implements SerializerAwareInterface
      {
          public function serialize($data, $format, array $context)
          {
              $this->serializer->serialize($data, $format, $context);
              // Custom logic
          }
      }
      
  2. Override Default Serializer

    • Replace the default serializer in services.yaml:
      services:
          bazinga.rest.serializer:
              class: App\Serializer\CustomSerializer
              arguments: ['@bazinga.rest.serializer.builder']
      
  3. Add Custom Metadata

    • Extend the bundle’s metadata system to add custom annotations or attributes:
      use Bazinga\RestExtraBundle\Metadata\MetadataInterface;
      
      class CustomMetadata implements MetadataInterface
      {
      
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.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware