Installation Add the bundle via Composer:
composer require axs/api-bundle
Enable it in config/bundles.php:
return [
// ...
TAlexMoreno\AXSApiBundle\AXSApiBundle::class => ['all' => true],
];
Basic Configuration
Publish the default config (if needed) and adjust in config/packages/axs_api.yaml:
php bin/console config:dump-reference axs_api
First Use Case: API-Ready Entity Annotate an entity to enable API features (e.g., serialization, filtering):
use TAlexMoreno\AXSApiBundle\Annotation\ApiEntity;
#[ApiEntity]
#[ORM\Entity]
class Product
{
// ...
}
Automatic Serialization
The bundle adds API-friendly serialization to Doctrine entities via annotations (e.g., @ApiEntity). Example:
#[ApiEntity(serializationGroups: ["default", "admin"])]
class User {}
Use serializationGroups to control output (e.g., hide sensitive fields for non-admin users).
Filtering & Query Building Leverage the bundle’s query builder helpers to add API-specific filters:
use TAlexMoreno\AXSApiBundle\Query\ApiFilterBuilder;
$filterBuilder = new ApiFilterBuilder($entityManager, Product::class);
$query = $filterBuilder
->addFilter('price', '>', 100)
->addFilter('category', '=', 'electronics')
->getQuery();
use TAlexMoreno\AXSApiBundle\Serializer\ApiSerializerInterface;
class CustomUserSerializer implements ApiSerializerInterface
{
public function serialize($data, string $format, array $context = []): array
{
// Custom logic (e.g., flatten nested objects)
return [
'id' => $data->getId(),
'name' => $data->getFullName(), // Custom method
];
}
}
Register it in services.yaml:
services:
TAlexMoreno\AXSApiBundle\Serializer\ApiSerializerInterface:
class: App\Serializer\CustomUserSerializer
tags: ['axs_api.serializer']
API Resource Controllers Use the bundle’s traits to simplify API endpoints:
use TAlexMoreno\AXSApiBundle\Controller\ApiResourceController;
class ProductController extends ApiResourceController
{
public function __construct(private EntityManagerInterface $em) {}
#[Route('/products', methods: ['GET'])]
public function index(): Response
{
return $this->handleListRequest(Product::class);
}
}
The handleListRequest method automatically applies filtering, pagination, and serialization.
Dynamic API Routes
Generate API routes dynamically for all @ApiEntity classes:
php bin/console axs:api:generate-routes
ApiFilterBuilder:
$query = $filterBuilder->paginate(10, 2); // Page 2, 10 items/page
The bundle returns a PaginationResponse with metadata (e.g., total, page).Annotation Overhead
@ApiEntity). If your project uses attributes (PHP 8+), ensure backward compatibility or migrate annotations to attributes.#[ApiEntity] (if supported) or a migration tool like ramsey/annotation-to-attribute.Query Builder Conflicts
ApiFilterBuilder logic may conflict with existing query filters (e.g., Doctrine extensions like Gedmo).ApiFilterBuilder class or use event listeners to merge queries.Serialization Groups
serializationGroups in @ApiEntity may lead to unexpected field exposure.["default", "admin"]) and document them.Performance with Large Datasets
fetch="LAZY" in entity relations and limit query fields with SELECT.Enable API Debug Mode
Add this to config/packages/axs_api.yaml to log queries and filters:
debug: true
Check Serialization Context
Use Symfony’s SerializerContextBuilder to inspect active groups:
$context = $serializer->getContext();
dump($context['groups']); // ['default', 'admin']
Validate Annotations Run the bundle’s validation command to catch misconfigured entities:
php bin/console axs:api:validate-entities
Custom Filter Types Extend the filter system by adding new operators or data types:
use TAlexMoreno\AXSApiBundle\Query\Filter\FilterInterface;
class RangeFilter implements FilterInterface
{
public function apply(QueryBuilder $qb, string $field, mixed $value): void
{
$qb->andWhere("$field BETWEEN :min AND :max")
->setParameter('min', $value['min'])
->setParameter('max', $value['max']);
}
}
Register it in services.yaml:
services:
TAlexMoreno\AXSApiBundle\Query\Filter\FilterInterface:
tags: ['axs_api.filter']
arguments:
$type: 'range'
Event Listeners Hook into API lifecycle events (e.g., pre-serialize, post-query):
use TAlexMoreno\AXSApiBundle\Event\ApiEvent;
class CustomApiListener
{
public function onPreSerialize(ApiEvent $event): void
{
$data = $event->getData();
$data->setHiddenField(null); // Modify data before serialization
}
}
Subscribe in services.yaml:
services:
App\EventListener\CustomApiListener:
tags:
- { name: 'kernel.event_listener', event: 'axs_api.pre_serialize', method: 'onPreSerialize' }
Override Default Serializer Replace the default serializer globally:
# config/packages/axs_api.yaml
serializer:
default_serializer: App\Serializer\CustomSerializer
Caching Serialization Groups The bundle caches serialization groups for performance. Clear the cache if groups change:
php bin/console cache:clear
Doctrine Event Conflicts
Ensure the bundle’s event listeners (e.g., postLoad) don’t conflict with existing Doctrine lifecycle callbacks. Use priority tags if needed:
tags:
- { name: 'doctrine.event_listener', event: 'postLoad', priority: 255 }
How can I help you explore Laravel packages today?