Ограничитель валидатор не

Я следую учебнику Symfony по проверке формы.

Здесь $ title должен оцениваться как уникальное право, и это работает, но то же сообщение об ошибке отображается в поле $ content.

Кроме того, я также пытаюсь получить контент для проверки с помощью ограничения «Antiflood» и его «Validator». (когда я комментирую проверку заголовка и пытаюсь, по крайней мере, заставить работать Antiflood …), я понимаю, что это работает (форма не проверяется), но я не получил сообщение об ошибке …

Ошибка проверки заголовка (двойное сообщение)
введите описание изображения здесь

Ошибка с constraintValidator (работает, но без сообщения)
введите описание изображения здесь
Мое ограничение

<?php
// src/OC/PlatformBundle/Validator/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.";
}

Мой валидатор

<?php
// src/OC/PlatformBundle/Validator/AntifloodValidator.php

namespace OC\PlatformBundle\Validator;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class AntifloodValidator extends ConstraintValidator
{
public function validate($value, Constraint $constraint)
{
// Pour l'instant, on considère comme flood tout message de moins de 3 caractères
if (strlen($value) < 3) {
// C'est cette ligne qui déclenche l'erreur pour le formulaire, avec en argument le message de la contrainte
$this->context->addViolation($constraint->message);
}
}
}

Мой Adver.php

namespace OC\PlatformBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\PreUpdate;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use OC\PlatformBundle\Validator\Antiflood;

/**
* Advert
* @ORM\Entity()
* @ORM\Table(name="advert")
* @ORM\Entity(repositoryClass="OC\PlatformBundle\Entity\AdvertRepository")
* @ORM\HasLifecycleCallbacks()
* @UniqueEntity(fields="title", message="Une annonce existe déjà avec ce titre.")
*/
class Advert {

/**
* @ORM\OneToMany(targetEntity="OC\PlatformBundle\Entity\Application", mappedBy="advert")
*/
private $applications;

/**
* @ORM\ManyToMany(targetEntity="OC\PlatformBundle\Entity\Category", cascade={"persist"})
*/
private $categories;

/**
* @ORM\OneToOne(targetEntity="OC\PlatformBundle\Entity\Image", cascade={"persist", "remove"})
* @Assert\Valid()
*/
private $image;

/**
*
* @var boolean @ORM\Column(name="published", type="boolean")
*/
private $published = true;

/**
*
* @var integer @ORM\Column(name="id", type="integer")
*      @ORM\Id
*      @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;

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

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

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

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

/**
* @ORM\Column(name="updated_at", type="datetime", nullable=true)
*/
private $updatedAt;

/**
* @ORM\Column(name="nb_applications", type="integer", nullable=true)
*/
private $nbApplications;

/**
* @Gedmo\Slug(fields={"title"})
* @ORM\Column(length=128, unique=true)
*/
private $slug;

/**
* @ORM\ManyToMany(targetEntity="OC\PlatformBundle\Entity\AdvertSkill", mappedBy="adverts")
* @ORM\JoinColumn(nullable=false)
*/
private $advertSkills;
public function __construct() {
// Par défaut, la date de l'annonce est la date d'aujourd'hui
$this-&gt;date = new \Datetime ();
$this-&gt;categories = new ArrayCollection ();
$this-&gt;applications = new ArrayCollection ();
}

/**
* Get id
*
* @return integer
*/
public function getId() {
return $this-&gt;id;
}
public function setDate($date) {
$this-&gt;date = $date;
return $this;
}

/**
* Set date
*
* @param \DateTime $date
* @return Advert @ORM\PrePersist()
*/
public function setDateAuto() {
$this-&gt;date = new \Datetime ();
return $this;
}

/**
* Get date
*
* @return \DateTime
*/
public function getDate() {
return $this-&gt;date;
}

/**
* Set title
*
* @param string $title
* @return Advert
*/
public function setTitle($title) {
$this-&gt;title = $title;

return $this;
}

/**
* Get title
*
* @return string
*/
public function getTitle() {
return $this-&gt;title;
}

/**
* Set author
*
* @param string $author
* @return Advert
*/
public function setAuthor($author) {
$this-&gt;author = $author;

return $this;
}

/**
* Get author
*
* @return string
*/
public function getAuthor() {
return $this-&gt;author;
}

/**
* Set content
*
* @param string $content
* @return Advert
*/
public function setContent($content) {
$this-&gt;content = $content;

return $this;
}

/**
* Get content
*
* @return string
*/
public function getContent() {
return $this-&gt;content;
}

/**
* Set published
*
* @param boolean $published
* @return Advert
*/
public function setPublished($published) {
$this-&gt;published = $published;

return $this;
}

/**
* Get published
*
* @return boolean
*/
public function getPublished() {
return $this-&gt;published;
}

/**
* Set image
*
* @param \OC\PlatformBundle\Entity\Image $image
* @return Advert
*/
public function setImage(\OC\PlatformBundle\Entity\Image $image = null) {
$this-&gt;image = $image;

return $this;
}

/**
* Get image
*
* @return \OC\PlatformBundle\Entity\Image
*/
public function getImage(Image $image = null) {
return $this-&gt;image;
}

/**
* Add categories
*
* @param \OC\PlatformBundle\Entity\Category $categories
* @return Advert
*/
public function addCategory(Category $categories) {
$this-&gt;categories [] = $categories;

return $this;
}

/**
* Remove categories
*
* @param \OC\PlatformBundle\Entity\Category $categories
*/
public function removeCategory(Category $categories) {
$this-&gt;categories-&gt;removeElement ( $categories );
}

/**
* Get categories
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getCategories() {
return $this-&gt;categories;
}

/**
* Add applications
*
* @param \OC\PlatformBundle\Entity\Application $applications
* @return Advert
*/
public function addApplication(\OC\PlatformBundle\Entity\Application $applications) {
$this-&gt;applications [] = $applications;
$applications-&gt;setAdvert ( $this ); // /!\ Retenez : on modifie le setter d'un côté, et on utilise ensuite ce setter-là
return $this;
}

/**
* Remove applications
*
* @param \OC\PlatformBundle\Entity\Application $applications
*/
public function removeApplication(\OC\PlatformBundle\Entity\Application $applications) {
$this-&gt;applications-&gt;removeElement ( $applications );
}

/**
* Get applications
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getApplications() {
return $this-&gt;applications;
}
public function listAction() {
$listAdverts = $this-&gt;getDoctrine ()-&gt;getManager ()-&gt;getRepository ( 'OCPlatformBundle:Advert' )-&gt;getAdvertWithApplications ();

foreach ( $listAdverts as $advert ) {
// Ne déclenche pas de requête : les candidatures sont déjà chargées !
// Vous pourriez faire une boucle dessus pour les afficher toutes
$advert-&gt;getApplications ();
}

// …
}

/**
* Set updatedAt
*
* @param \DateTime $updatedAt
* @return Advert
*/
public function setUpdatedAt($updatedAt) {
$this-&gt;updatedAt = $updatedAt;

return $this;
}

/**
* Get updatedAt
*
* @return \DateTime
*/
public function getUpdatedAt() {
return $this-&gt;updatedAt;
}

/**
* @ORM\PreUpdate
*/
public function updateDate() {
$this-&gt;setUpdatedAt ( new \DateTime () );
}
public function increaseApplication() {
$this-&gt;nbApplications ++;
}
public function decreaseApplication() {
$this-&gt;nbApplications --;
}

/**
* Set nbApplications
*
* @param integer $nbApplications
* @return Advert
*/
public function setNbApplications($nbApplications) {
$this-&gt;nbApplications = $nbApplications;

return $this;
}

/**
* Get nbApplications
*
* @return integer
*/
public function getNbApplications() {
return $this-&gt;nbApplications;
}

/**
* Set slug
*
* @param string $slug
* @return Advert
*/
public function setSlug($slug) {
$this-&gt;slug = $slug;

return $this;
}

/**
* Get slug
*
* @return string
*/
public function getSlug() {
return $this-&gt;slug;
}

// /**
// * @Assert\True(message="Ce champs doit être rempli")
// */
// public function isTitle()
// {
// return false;
// }

/**
* @Assert\Callback
*/
public function isContentValid(ExecutionContextInterface $context) {

// // MOT INDESIRABLES
// $forbiddenWords = array('échec', 'abandon');

// // On vérifie que le contenu ne contient pas l'un des mots
// if (preg_match('#'.implode('|', $forbiddenWords).'#', $this-&gt;getContent())) {
// // La règle est violée, on définit l'erreur
// // $context
// // -&gt;buildViolation('Contenu invalide car il contient un mot interdit.') // message
// // -&gt;atPath('content') // attribut de l'objet qui est violé
// // -&gt;addViolation() // ceci déclenche l'erreur, ne l'oubliez pas
// // ;
// $context-&gt;addViolation("Contenu invalide"); //!!!CORRECTE!!!
// }
}
}{# src/OC/PlatformBundle/Resources/views/Advert/form.html.twig #}

<h3>Formulaire d'annonce</h3>

<div class="well">
{{ form_start(form, {'attr': {'class': 'form-horizontal'}}) }}

{# Les erreurs générales du formulaire. #}
{{ form_errors(form) }}

<div class="form-group">
{# Génération du label. #}
{{ form_label(form.title, "Titre de l'annonce", {'label_attr': {'class': 'col-sm-3 control-label'}}) }}

{# Affichage des erreurs pour ce champ précis. #}
{{ form_errors(form.title) }}

<div class="col-sm-4">
{# Génération de l'input. #}
{{ form_widget(form.title, {'attr': {'class': 'form-control'}}) }}
</div>
</div>

{# Idem pour un autre champ. #}
<div class="form-group">
{{ form_label(form.content, "Contenu de l'annonce", {'label_attr': {'class': 'col-sm-3 control-label'}}) }}
{{ form_errors(form.title) }}
<div class="col-sm-4">
{{ form_widget(form.content, {'attr': {'class': 'form-control'}}) }}
</div>
</div>

{# Génération du label + error + widget pour un champ #}
{% if form.date is defined %}
<div class="form-group">
{{ form_label(form.date, "Date de sousmission", {'label_attr': {'class': 'col-sm-3 control-label'}}) }}
{{ form_errors(form.date) }}
<div class="col-sm-4">
{{ form_widget(form.date) }}
</div>
</div>
{% endif %}
<div class="form-group">
{{ form_label(form.author, "Auteur", {'label_attr': {'class': 'col-sm-3 control-label'}}) }}
{{ form_errors(form.author) }}
<div class="col-sm-4">
{{ form_widget(form.author) }}
</div>
</div>
{% if form.published is defined %}
<div class="form-group">
{{ form_label(form.published, "Published", {'label_attr': {'class': 'col-sm-3 control-label'}}) }}
{{ form_errors(form.published) }}
<div class="col-sm-4">
{{ form_widget(form.published) }}
</div>
</div>
{% endif %}
{% if advert.image is defined %}
<img
src="{{ asset(advert.image.webPath) }}"alt="{{ advert.image.alt }}"/>
{% endif %}
<div class="form-group">
{{ form_label(form.save, "", {'label_attr': {'class': 'col-sm-3 control-label'}}) }}
<div class="col-sm-4">
{# Pour le bouton, pas de label ni d'erreur, on affiche juste le widget #}
{{ form_widget(form.save, {'attr': {'class': 'btn btn-primary'}}) }}
</div>
</div>

{# Génération automatique des champs pas encore écrits.
Dans cet exemple, ce serait le champ CSRF (géré automatiquement par Symfony !)
et tous les champs cachés (type « hidden »). #}
{{ form_rest(form) }}

{# Fermeture de la balise <form> du formulaire HTML #}
{{ form_end(form) }}
</div>

2

Решение

Понял! У меня было {{form_errors (form.title)}} вместо {{form_errors (form.content)}}} в шаблоне ветки: S

0

Другие решения

Других решений пока нет …