cyberspectrum/api-platform-toolkit-bundle
Symfony bundle adding API Platform toolkit features: enable custom ExpressionLanguage providers via tagged services, and optional LexikJWT helpers including Swagger/OpenAPI login endpoint docs and configurable default token TTL and login URL.
Installation
composer require cyberspectrum/api-platform-toolkit-bundle
Add the bundle to config/bundles.php:
return [
// ...
Cyberspectrum\ApiPlatformToolkitBundle\ApiPlatformToolkitBundle::class => ['all' => true],
];
Basic Configuration
Enable the bundle in config/packages/api_platform_toolkit.yaml:
api_platform_toolkit:
enable_expression_language: true
lexik_jwt:
add_documentation: true
default_ttl: 3600
login_url: '/api/login_check'
First Use Case: Custom Expression Language Implement a custom provider for API Platform’s expression language:
// src/ExpressionLanguage/CustomProvider.php
namespace App\ExpressionLanguage;
use ApiPlatform\Core\ExpressionLanguage\ExpressionFunctionProviderInterface;
class CustomProvider implements ExpressionFunctionProviderInterface
{
public function getFunctions(): array
{
return [
'custom_func' => [$this, 'customFunc'],
];
}
public function customFunc($arg1, $arg2)
{
return $arg1 . ' ' . $arg2;
}
}
Register it as a tagged service in config/services.yaml:
services:
App\ExpressionLanguage\CustomProvider:
tags:
- { name: csap_toolkit.security.expression_language }
Dynamic Security Rules Use the expression language to dynamically enforce security rules in API resources:
// src/Entity/Book.php
use ApiPlatform\Core\Annotation\Security;
#[Security("is_granted('ROLE_ADMIN') or custom_func('user', 'can_edit')")]
Custom Filtering Extend API Platform’s filtering with custom logic:
#[ApiFilter(CustomFilter::class, properties: ['customField'])]
Token TTL Configuration Override default TTL per request via headers or query params:
# config/packages/lexik_jwt_authentication.yaml
lexik_jwt_authentication:
token_extractors:
- authorization_header
- query_parameter
Use in API calls:
GET /api/login_check?ttl=900
Documentation Integration
Automatically include JWT login endpoint in Swagger/OpenAPI docs by enabling add_documentation.
Tagging Services
Always tag custom expression providers with csap_toolkit.security.expression_language for automatic registration.
JWT Customization Extend LexikJWT’s configuration to support TTL overrides:
api_platform_toolkit:
lexik_jwt:
min_ttl: 60 # Optional: Add min/max TTL constraints
max_ttl: 86400
Testing Mock expression providers in tests:
$container->set('custom_provider', $this->createMock(CustomProvider::class));
Expression Language Scope
@Security annotations).JWT Configuration Conflicts
lexik_jwt in api_platform_toolkit does not remove LexikJWT’s core functionality—only the bundle’s extensions.lexik_jwt_authentication is properly configured in config/packages/lexik_jwt_authentication.yaml.Tagging Errors
csap_toolkit.security.expression_language) will silently ignore your provider.bin/console debug:container csap_toolkit.security.expression_language
Expression Language Issues Enable debug mode and check logs for:
bin/console debug:container --tag=csap_toolkit.security.expression_language
If a provider isn’t loaded, confirm it’s autowired and tagged correctly.
JWT TTL Overrides
Debug TTL values in the JWTCreatedEvent listener:
public function onJWTCreated(JWTCreatedEvent $event)
{
$data = $event->getData();
var_dump($data['ttl']); // Check if custom TTL is applied
}
Custom Expression Functions Extend the provider interface to add complex logic:
public function getFunctions(): array
{
return [
'user_has_role' => [$this, 'checkUserRole'],
'date_between' => [$this, 'checkDateRange'],
];
}
JWT Metadata
Add custom claims to tokens via a JWTCreatedEvent subscriber:
public function onJWTCreated(JWTCreatedEvent $event)
{
$event->setData([
...$event->getData(),
'custom_claim' => 'value',
]);
}
Documentation Enhancements Override the Swagger generator to include additional JWT details:
# config/packages/api_platform.yaml
api_platform:
formats:
jsonld:
mime_types: ['application/ld+json']
swagger:
versions: [3]
How can I help you explore Laravel packages today?