## 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],
];
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(),
];
}
}
Register the Serializer
Configure the bundle in config/packages/bazinga_rest_extra.yaml:
bazinga_rest_extra:
serializers:
App\Entity\User: App\Serializer\UserSerializer
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');
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');
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']]);
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']
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]);
Serializer Registration Order
App\Serializer\UserSerializer is autowired or manually registered in services.yaml:
services:
App\Serializer\UserSerializer:
tags: ['bazinga_rest.serializer']
Circular References
User->posts->author->posts) causes infinite loops.SerializerBuilderInterface to limit depth or implement custom logic:
$builder->add('user.posts', 'App\Serializer\PostSerializer', ['max_depth' => 1]);
Validation Overhead
Deprecated Symfony 2/3 Features
config/services.yaml or use a compatibility layer like symfony/flex.Context Propagation
$context = array_merge($context, ['parent_key' => 'value']);
Enable Verbose Serialization
debug: true in context to log serialization steps:
$serializer->serialize($user, 'json', ['debug' => true]);
Check Serializer Groups
$validator->validate($data, User::class, ['groups' => ['Default', 'create']]);
Inspect Events
$event->getData(); // Inspect input data
$event->getObject(); // Inspect the original object
Custom Serializer Awareness
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
}
}
Override Default Serializer
services.yaml:
services:
bazinga.rest.serializer:
class: App\Serializer\CustomSerializer
arguments: ['@bazinga.rest.serializer.builder']
Add Custom Metadata
use Bazinga\RestExtraBundle\Metadata\MetadataInterface;
class CustomMetadata implements MetadataInterface
{
How can I help you explore Laravel packages today?