2

I've been trying to create a custom validation constraint with parameters, using services on Symfony3.

The problem is that I get an exception after submitting my form :

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

I understand Symfony couldn't hydrate the AntifloodValidator's constructor with the parameters given in services.yml.

Here is my code :

In 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 }

In 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
  }
}

In 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)
  {
   ...

And in Advert.php (my Entity) :

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;

In went through the documentation multiple times and didn't find anything. Same thing here on stackoverflow.

Any idea ?

1
  • Is the oc_platform.validator.antiflood actually registered in your service container? You can use the debug:container command to check that. Commented Jan 13, 2016 at 9:58

2 Answers 2

1

If you are injecting to your service (Constraint) the request stack it should have a request scope like this :

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
Sign up to request clarification or add additional context in comments.

6 Comments

Weird. I didn't see it written in the doc : here. It doesn't resolve my problem though. Why is it necessary ?
Yeah I think you should add it because if you are injecting a request stack in your service so he noud to be request scoped which mean that your service will have the same life time as your request
The request stack was precisely introduced to get rid of the request scope (the whole scope concept is deprecated since Symfony 2.8 and was removed with Symfony 3).
I see. But if it's decrepated, why does the documentation still talk about it without warning about its decrepation ?
xabbuh is write it's deprecated just here is the correct link of doc symfony.com/doc/master/cookbook/service_container/scopes.html
|
1

In the Antiflood class, the function must be named validatedBy, and not validateBy...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.