Installation Add the package via Composer:
composer require api-platform/validator
No additional configuration is required for basic usage—it integrates seamlessly with Symfony Validator.
First Use Case Use it to validate API resource data before serialization/deserialization. Example:
use ApiPlatform\Validator\ValidatorInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface as SymfonyValidator;
// In a controller or service
$validator = new \ApiPlatform\Validator\Validator(new SymfonyValidator());
$errors = $validator->validate($dataObject);
if (count($errors) > 0) {
// Handle validation errors (e.g., return HTTP 400)
}
Where to Look First
ValidatorInterface and Validator classes.api-platform/core for automatic validation in API resources.Validation in API Resources
Extend ApiPlatform\Metadata\ApiResource and use Symfony’s validation annotations:
use Symfony\Component\Validator\Constraints as Assert;
#[ApiResource]
class Book
{
#[Assert\NotBlank]
public string $title;
#[Assert\Positive]
public int $pageCount;
}
API Platform’s Validator automatically validates these constraints during deserialization.
Manual Validation in Services Use the validator in custom services:
public function updateBook(Book $book, array $data)
{
$validator = app(ValidatorInterface::class);
$errors = $validator->validate($data);
if ($errors->count() > 0) {
throw new \RuntimeException('Validation failed');
}
// Proceed with update
}
Validation Groups Leverage Symfony’s validation groups for context-specific rules:
#[Assert\Callback(groups: ['create'])]
public function validateCreate(ExecutionContextInterface $context)
{
if (empty($this->title)) {
$context->buildViolation('Title is required.')
->atPath('title')
->addViolation();
}
}
Call with:
$validator->validate($book, ['create']);
Custom Validation Logic Create reusable validators:
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class UniqueSlugValidator extends ConstraintValidator
{
public function validate($value, Constraint $constraint)
{
if (Book::where('slug', $value)->exists()) {
$this->context->buildViolation($constraint->message)
->addViolation();
}
}
}
Annotate your entity:
#[UniqueSlug(message: 'Slug must be unique.')]
public string $slug;
Integration with API Platform’s Operation
Use Validator in custom operations (e.g., POST/PUT):
#[ApiResource(operations: [
new Post(validator: new Validator(new SymfonyValidator())),
])]
class Book {}
Circular References Validate nested objects carefully to avoid infinite loops:
// Disable validation for circular references
$validator->validate($object, null, ['disable_circular_reference_check' => true]);
Lazy-Loaded Properties Ensure validated properties are loaded before validation:
$book->load('author'); // If author is lazy-loaded
$validator->validate($book);
Overriding Default Groups
API Platform uses Default and create/update groups by default. Override cautiously:
# config/validator/validation.yaml
ApiPlatform\Validator\Validator:
groups: [custom_group]
Performance with Large Datasets Avoid validating entire collections unnecessarily. Use partial validation:
$validator->validateProperty($object, 'title');
Constraint Conflicts
Ensure constraints don’t conflict (e.g., @Assert\Length(min=5) + @Assert\Max(3)).
Enable Validation Tracing Symfony’s validator supports tracing:
$validator->validate($object, null, ['trace' => true]);
Inspect $errors->getTrace() for debugging.
Check Constraint Names Use fully qualified constraint names for clarity:
#[Assert\Type(type: 'string', message: 'Must be a string')]
Validate with null Groups
Test all constraints by passing an empty array:
$validator->validate($object, []); // Runs all groups
Custom Validation Context
Extend Symfony\Component\Validator\ExecutionContextInterface for complex logic:
$context = $validator->getContext();
$context->getRoot()->get('custom_data');
Event Listeners Attach listeners to validation events:
$validator->addListener('pre_validate', function ($event) {
$event->getObject()->setTempFlag(true);
});
Constraint Compilation Override constraint compilation for performance:
use Symfony\Component\Validator\Mapping\ClassMetadata;
$metadata = new ClassMetadata($class);
$metadata->addPropertyConstraint('title', new NotBlank());
$validator->compileMapping($metadata);
Integration with API Platform’s State Processor
Combine with ApiPlatform\State\ProcessorInterface for pre/post-validation logic:
$processor = new Processor($validator);
$processor->process($data, $operation);
Custom Error Formats Format errors for API responses:
$errors = $validator->validate($object);
$serialized = $errors->getPropertyPaths(); // Array of paths with errors
How can I help you explore Laravel packages today?