带参数的Symfony3自定义验证约束抛出异常

时间:2016-01-12 17:51:47

标签: php validation constraints symfony

我一直在尝试使用Symfony3上的服务创建带参数的自定义验证约束。

问题是我在提交表单后遇到异常:

Catchable Fatal Error: Argument 1 passed to OC\PlatformBundle\Validator\AntifloodValidator::__construct() must be an instance of Symfony\Component\HttpFoundation\RequestStack, none given, called in C:\wamp\www\Symfony\vendor\symfony\symfony\src\Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory.php on line 71 and defined

我知道Symfony无法使用services.yml中给出的参数来保护AntifloodValidator的构造函数。

这是我的代码:

在services.yml:

oc_platform.validator.antiflood:
        class: OC\PlatformBundle\Validator\AntifloodValidator
        arguments: ['@request_stack', '@doctrine.orm.entity_manager']
        tags:
            - { name: validator.constraint_validator, alias: oc_platform_antiflood }

在Antiflood.php中:

namespace OC\PlatformBundle\Validator;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class Antiflood extends Constraint
{
  public $message = "Vous avez déjà posté un message il y a moins de 15 secondes, merci d'attendre un peu.";

  public function validateBy()
  {
    return 'oc_platform_antiflood'; // Ici, on fait appel à l'alias du service
  }
}

在AntifloodValidator.php中:

namespace OC\PlatformBundle\Validator;

use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class AntifloodValidator extends ConstraintValidator
{
  private $requestStack;
  private $em;

  // Les arguments déclarés dans la définition du service arrivent au constructeur
  // On doit les enregistrer dans l'objet pour pouvoir s'en resservir dans la méthode validate()
  public function __construct(RequestStack $requestStack, EntityManagerInterface $em)
  {
    $this->requestStack = $requestStack;
    $this->em           = $em;
  }

  public function validate($value, Constraint $constraint)
  {
   ...

在Advert.php(我的实体)中:

namespace OC\PlatformBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Context\ExecutionContextInterface;

use OC\PlatformBundle\Validator as CustomAssert;

/**
 * Advert
 * 
 * @ORM\Table(name="advert")
 * @ORM\Entity(repositoryClass="OC\PlatformBundle\Repository\AdvertRepository")
 * @ORM\HasLifecycleCallbacks()
 * @UniqueEntity(fields="title", message="Une annonce existe déjà avec ce titre.")
 */
class Advert
{
  /**
   * @ORM\Column(name="id", type="integer")
   * @ORM\Id
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  private $id;

  /**
   * @ORM\Column(name="date", type="datetime")
   * @Assert\DateTime()
   */
  private $date;

  /**
   * @ORM\Column(name="title", type="string", length=255, unique=false)
   * @Assert\Length(min=10)
   */
  private $title;

  /**
   * @ORM\Column(name="author", type="string", length=255)
   * @Assert\Length(min=2)
   */
  private $author;

  /**
   * @ORM\Column(name="content", type="text")
   * @Assert\NotBlank()
   * @CustomAssert\Antiflood
   */
  private $content;

多次浏览文档并没有找到任何内容。 stackoverflow上也是一样的东西。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

如果您要向服务(Constraint)注入请求堆栈,它应该有一个这样的请求范围:

oc_platform.validator.antiflood:
        class: OC\PlatformBundle\Validator\AntifloodValidator
        arguments: ['@request_stack', '@doctrine.orm.entity_manager']
        tags:
            - { name: validator.constraint_validator, alias: oc_platform_antiflood }
        scope: request

答案 1 :(得分:1)

Antiflood 类中,该函数必须命名为validate d By,而不是validateBy ...