Problème custom validation Symfony3

Le problème exposé dans ce sujet a été résolu.

Bonjour dans le tutoriel Créez une API REST avec Symfony 3 dans la partie III - 3.Créer une ressource avec des relations on crée un custom validator, celui-ci n 'est pas pris en compte chez moi j 'ai tjs l erreur :

1
2
3
4
{
  "code": 500,
  "message": "An exception occurred while executing 'INSERT INTO price (type, value, place_id) VALUES (?, ?, ?)' with params [\"less_than_12\", 0, 17]:\n\nSQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'less_than_12-17' for key 'prices_type_place_unique'"
}

Voici mon code :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# src/AppBundle/Validator/Constraints/PriceTypeUnique.php

namespace AppBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class PriceTypeUnique extends Constraint
{
    public $message = 'A place cannot contain prices with same type';
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# src/AppBundle/Validator/Constraints/PriceTypeUniqueValidator.php

namespace AppBundle\Validator\Constraints;

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

class PriceTypeUniqueValidator extends ConstraintValidator
{
    public function validate($prices, Constraint $constraint)
    {
        if (!is_array($prices)) {
            return;
        }
        $pricesType = [];

        foreach ($prices as $price) {
            if (in_array($price->getType(), $pricesType, false)) {
                $this->context->buildViolation($constraint->message)
                    ->addViolation();
                return; // Si il y a un doublon, on arrête la recherche
            } else {
                // Sauvegarde des types de prix déjà présents
                $pricesType[] = $price->getType();
            }
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# src/AppBundle/Entity/Place.php

namespace AppBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use AppBundle\Validator\Constraints as AppBundleAssert;

/**
 * Place
 *
 * @ORM\Table(name="place", uniqueConstraints={@ORM\UniqueConstraint(name="place_name_unique",columns={"name"})})
 * @ORM\Entity()
 */
class Place
{
...
/**
     * @var Price[]
     *
     * @Groups({"place"})
     * @ORM\OneToMany(targetEntity="Price", mappedBy="place")
     * @Assert\Valid()
     * @AppBundleAssert\PriceTypeUnique()
     */
    private $prices;
...
}

Pour la validation j'ai utilisé les annotations au lieu du fichier yaml. Je ne vois pas ou se trouve l 'erreur.

La validation est correctement activée dans le fichier config.yml et fonctionnel car elle fonctionne sur d'autres champs.

Merci d 'avance

Salut,

Tout d'abord je tiens à te dire que ton validateur fonctionne sinon tu aurais une toute autre erreur, sauf qu'elle ne fonctionne pas comme tu t'y attends. Le problème sont les lignes 12 à 14, en fait, le return est executé. Il faut plutôt vérifier si ce n'est pas un ArrayCollection (j'ai eu le même problème :D)

1
2
3
4
5
6
7
8
<?php
if (!($prices instanceof \Doctrine\Common\Collections\ArrayCollection)) {
    return;
}
//ou avec un use Doctrine\Common\Collections\ArrayCollection;
if (!($prices instanceof ArrayCollection)) {
    return;
}

Edit: Thanks bestcoder

+2 -0

Salut,

Il y a effectivement un soucis dans le cours. J'avais changé le type de prices sans mettre à jour le validateur. Je vais le corriger de ce pas (et rajouter un test fonctionnel dessus par la même occasion ^^ ).

Par contre pour la première solution d'azeupaul, il faut que le namespace commence par un \.

1
2
3
4
<?php
if (!($prices instanceof \Doctrine\Common\Collections\ArrayCollection)) {
    return;
}
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte