【问题标题】:How to make a Symfony Callback validator Doctrine aware?如何让 Symfony 回调验证器学说知道?
【发布时间】:2016-10-05 06:22:37
【问题描述】:

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

所以问题,简而言之:有可能实现吗?以哪种方式?

【问题讨论】:

  • 你需要一个自定义的约束和验证器来注入 Doctrine 服务。你试过吗?
  • 从未尝试过,我在上面找到了一些文档,但对于我需要的东西来说似乎有点复杂。如果是解决方案,我会实施这个
  • 我没那么复杂。看看这里。 symfony.com/doc/current/validation/custom_constraint.html如果您在实施时遇到问题,我很乐意提供帮助。
  • @dragoste:我根据您的建议创建了答案。我对测试优先级的问题不属于这个,所以非常感谢你给我我需要的提示:)

标签: php validation doctrine-orm symfony


【解决方案1】:

根据@dragoste 在 cmets 中所说的,我搜索了如何使用自己的约束来实现。

解决方案是使用Custom Constraint。知道要做什么文件和做什么有点混乱,所以这是我所做的。

为了向您解释我的文件是什么,我们的目标是验证租金,而不是根据租金的制作方式,而只是检查同一时刻是否没有租金。这就是为什么我必须使用包含 Doctrine 的约束。

在包的根目录中创建 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
    }
}

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

在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()
            ;
        }
    }
}

我们快完成了,我们必须将它声明为服务,所以这里我们在 Resources/config

中编辑 services.yml
services:
    # [...]
    validator.rent_dates:
        class: ApiBundle\Validator\RentDatesValidator
        tags:
            - { name: validator.constraint_validator }
        arguments: [ "@doctrine" ]

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

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

ApiBundle\Entity\Rent:
    constraints:
        - ApiBundle\Validator\Constraints\RentDatesConstraint: ~

我们完成了!将您的对象传递给验证器服务时,验证将起作用。

您可以注意到这是使用 YAML 制作的,我个人更喜欢这种做事方式,因为它分隔了各个部分(实体定义、数据库架构、验证文件……),但您可以使用注释、XML 来做到这一点甚至是纯 PHP。这取决于您,因此如果您想查看更多语法,您仍然可以访问 Symfony 文档的链接以了解如何执行此操作。

【讨论】:

    猜你喜欢
    • 2016-03-20
    • 2018-02-22
    • 2012-06-11
    • 2016-10-16
    • 1970-01-01
    • 2012-05-09
    • 2015-02-28
    • 2016-03-31
    • 1970-01-01
    相关资源
    最近更新 更多