如何使Symfony回调验证器学到原理?

Ala*_*IER 2 php validation symfony doctrine-orm

如标题中所述,我实际上需要使用Symfony创建一个验证过程。我正在使用YAML文件,一切正常。但是在某些情况下,我需要先检查数据库,然后再说数据已验证。我在Callback方法中进行搜索,但实际上它只允许我基本上检查这些值。我进行了搜索以进行依赖项注入,甚至将定义的服务作为回调传递,但这样做也无济于事。

简而言之,问题是:能否实现?以何种方式?

Ala*_*IER 5

用@dragoste在评论中说的话,我搜索了如何在自己的约束下实现。

解决方案是使用“ 自定义约束”。知道要制作什么文件以及要做什么,这有点混乱,所以这就是我所做的。

为了向您解释我的文件,我们的目的是验证租金,而不是根据租金的方式确定,而只是检查同时没有租金。这就是为什么我必须在其中使用带有约束的约束。

在包根目录中创建Validator文件夹。然后,在Validator文件夹中添加一个Constraints文件夹。

Validaor / Constraints文件夹中创建一个文件RentDatesConstraint.php。外观如下:

<?php

namespace ApiBundle\Validator\Constraints;

use ApiBundle\Validator\RentDatesValidator;
use Symfony\Component\Validator\Constraint;

class RentDatesConstraint extends Constraint
{
    public $message = 'The beginning and ending date of the rent are not available for this vehicle.'; // note that you could use parameters inside it, by naming it with % to surround it

    /**
     * @inheritdoc
     */
    public function validatedBy()
    {
        return RentDatesValidator::class; // this is the name of the class that will be triggered when you need to validate this constraint
    }

    /**
     * @inheritdoc
     */
    public function getTargets()
    {
        return self::CLASS_CONSTRAINT; // says that this constraints is a class constraint
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您已经创建了自己的类约束,您必须创建自己的验证器。

Validator文件夹中创建一个文件RentDatesValidator.php

<?php

namespace ApiBundle\Validator;

use Doctrine\Bundle\DoctrineBundle\Registry;
use Doctrine\Common\Collections\Collection;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class RentDatesValidator extends ConstraintValidator
{
    /**
     * @var Registry $doctrine
     */
    private $doctrine;

    /**
     * RentDatesValidator constructor.
     * @param Registry $_doctrine
     */
    public function __construct(Registry $_doctrine)
    {
        $this
            ->setDoctrine($_doctrine)
        ;
    }

    /**
     * @param Registry $_doctrine
     * @return $this
     */
    public function setDoctrine(Registry $_doctrine)
    {
        $this->doctrine = $_doctrine;
        return $this;
    }

    /**
     * @inheritdoc
     * @param Rent $_value
     */
    public function validate($_value, Constraint $_constraint)
    {
        //do your stuff here

        if ($testFails) {
            $this
                ->context
                ->buildViolation($_constraint->message) // here you can pass an array to set the parameters of the string, surrounded by %
                ->addViolation()
            ;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我们差不多完成了,我们必须将其声明为服务,因此在这里我们在Resources / config中编辑services.yml

services:
    # [...]
    validator.rent_dates:
        class: ApiBundle\Validator\RentDatesValidator
        tags:
            - { name: validator.constraint_validator }
        arguments: [ "@doctrine" ]
Run Code Online (Sandbox Code Playgroud)

您可以在这里注意到我传递了@doctrine服务,但是实际上您可以传递任何想要的服务,甚至很多,只要您正确定义RentDatesValidator类以在其构造函数中接受这些服务即可。

现在,您要做的就是在验证中使用它。在这里,我们在Resource / config / validation中编辑Rent.yml以仅添加以下行:

ApiBundle\Entity\Rent:
    constraints:
        - ApiBundle\Validator\Constraints\RentDatesConstraint: ~
Run Code Online (Sandbox Code Playgroud)

我们完了!将对象传递给验证程序服务时,验证将起作用。

您可能会注意到,这是使用YAML进行的,我个人更喜欢这种处理方式,因为它将每个部分(实体定义,数据库架构,验证文件等)分开,但是您可以使用批注,XML甚至纯PHP。这取决于您,因此,如果您想查看更多语法,您仍然可以转到Symfony文档的链接以了解如何执行此操作。