我想在控制器中的各种查询参数上使用自定义验证器。文档给出了这个例子:
// validate a query parameter (a hash in this case)
$incomingHashConstraint = new CustomAssert\IncomingHash();
// use the validator to validate the value
// If you're using the new 2.5 validation API (you probably are!)
$errorList = $this->get('validator')->validate(
$incomingHash,
$incomingHashConstraint
);
if (0 === count($errorList)) {
// ... this IS a valid hash
} else {
// this is *not* a valid hash
$errorMessage = $errorList[0]->getMessage();
// ... do something with the error
throw $this->createNotFoundException('Not a valid hash ID ' . $incomingHash);
}
在很多控制器中使用它非常笨重。理想情况下,我可以使用自定义验证器作为路线中的要求,但这似乎不是一种选择。这些验证器应该是服务吗?理想情况下,我想要像
这样的东西if(!isValid($incomingHash, IncomingHashConstraint)) {
throw \Exception(); }
有关组织此方法的最佳方法的任何建议吗?谢谢!
答案 0 :(得分:4)
有一种非常简单和干净的方式。
我将给出一个有效的例子,但如果你想要一个完整的例子,那么it is here。如果你应用它,你将拥有一个非常薄的控制器。字面上不超过15行。这样你就可以了解@SergioIvanuzzo上面所说的内容。
安装jms / serializer-bundle Doc
"frameworks": {
"dnx451": { },
"dnxcore50": {
"dependencies": {
"System.Data.SqlClient": "4.0.0-beta-23516"
}
}
}
CUSTOM MODEL CLASS
composer require jms/serializer-bundle
// in AppKernel::registerBundles()
$bundles = array(
// ...
new JMS\SerializerBundle\JMSSerializerBundle(),
// ...
);
您的自定义验证员类
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;
}
<强> CONTROLLER 强>
如果您不将控制器用作服务,则可以像上面一样直接使用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!
}
}
访问validator
和serializer
个服务。
$this->get('put_the_name_here')
<强>实施例强>
请求1
...
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;
}
}
回复1
{
"id": 66,
"name": "Acyraaaaa",
"dob": "11/11/1111",
"whatever": "test"
}
请求2
Application\FrontendBundle\Model\Person Object
(
[id] => 66
[name] => Acyraaaaa
[dob] => 11/11/1111
[whatever] => test
)
回复2
{
"id": "Hello",
"name": "Acyra",
"dob": "28/11/2014"
}
如果你去链接我给你上面并应用其余的然后你会得到正确的错误信息,如:
400 Bad request
Some errors