There is a very easy and clean way of doing it.
- The Request payload gets mapped to your custom model class and validated against you custom validation class.
- If there is an error then you get the list of errors.
- If there is no error then you get your model class back with all the
payload data are mapped to the relevant properties in it then you
use that model class for further logic(you should do extra logic in
a service class not in controller).
I'll give a working example but if you want a full example then it is here. If you apply it, you'll have a very very thin controller. Literally no more than 15 lines. This way you'll have what exactly what @SergioIvanuzzo said above.
INSTALL jms/serializer-bundle Doc
composer require jms/serializer-bundle
// in AppKernel::registerBundles()
$bundles = array(
// ...
new JMS\SerializerBundle\JMSSerializerBundle(),
// ...
);
CUSTOM MODEL CLASS
namespace Application\FrontendBundle\Model;
use Application\FrontendBundle\Validator\Constraint as PersonAssert;
use JMS\Serializer\Annotation as Serializer;
/**
* @PersonAssert\Person
*/
class Person
{
/**
* @var int
* @Serializer\Type("integer")
*/
public $id;
/**
* @var string
* @Serializer\Type("string")
*/
public $name;
/**
* @var string
* @Serializer\Type("string")
*/
public $dob;
/**
* @var string
* @Serializer\Type("string")
*/
public $whatever;
}
YOUR CUSTOM VALIDATOR CLASSES
namespace Application\FrontendBundle\Validator\Constraint;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
*/
class Person extends Constraint
{
public function getTargets()
{
return self::CLASS_CONSTRAINT;
}
public function validatedBy()
{
return get_class($this).'Validator';
}
}
namespace Application\FrontendBundle\Validator\Constraint;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class PersonValidator extends ConstraintValidator
{
public function validate($person, Constraint $constraint)
{
if (!is_numeric($person->id)) {
$this->context->buildViolation('Id must be a numeric value.')->addViolation();
}
if ($person->name == 'Acyra') {
$this->context->buildViolation('You name is weird.')->addViolation();
}
if ($person->dob == '28/11/2014') {
$this->context->buildViolation('You are too young.')->addViolation();
}
// I'm not interested in validating $whatever property of Person model!
}
}
CONTROLLER
If you don't use your controller as a service then you can access validator and serializer services directly with $this->get('put_the_name_here') like you did above.
...
use JMS\Serializer\SerializerInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
....
/**
* @Route("person", service="application_frontend.controller.bank")
*/
class PersonController extends Controller
{
private $validator;
private $serializer;
public function __construct(
ValidatorInterface $validator,
SerializerInterface $serializer
) {
$this->validator = $validator;
$this->serializer = $serializer;
}
/**
* @param Request $request
*
* @Route("/person")
* @Method({"POST"})
*
* @return Response
*/
public function personAction(Request $request)
{
$person = $this->validatePayload(
$request->getContent(),
'Application\FrontendBundle\Model\Person'
);
if ($person instanceof Response) {
return $person;
}
print_r($person);
// Now you can carry on doing things in your service class
}
private function validatePayload($payload, $model, $format = 'json')
{
$payload = $this->serializer->deserialize($payload, $model, $format);
$errors = $this->validator->validate($payload);
if (count($errors)) {
return new Response('Some errors', 400);
}
return $payload;
}
}
EXAMPLES
Request 1
{
"id": 66,
"name": "Acyraaaaa",
"dob": "11/11/1111",
"whatever": "test"
}
Response 1
Application\FrontendBundle\Model\Person Object
(
[id] => 66
[name] => Acyraaaaa
[dob] => 11/11/1111
[whatever] => test
)
Request 2
{
"id": "Hello",
"name": "Acyra",
"dob": "28/11/2014"
}
Response 2
400 Bad request
Some errors
If you go to link I gave you above and apply the rest then you would actually get proper error messages like:
{
"errors": {
"id": "Id must be a numeric value.",
"name": "You name is weird.",
"dob": "You are too young."
}
}