Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The constraint cannot be put on properties or getters

I try create custom constraint in symfony 3

I have error

The constraint App\Bundle\MyBundle\Validator\Constraints\Code cannot be put on properties or getters

<?php
// vendor/app/mybundle/Validator/Constraints/Code.php

namespace App\Bundle\MyBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;


class Code extends Constraint
{
    public $message = 'Error validate message!!!';
    public function validatedBy()
    {
        return 'alias_name';
    }

    public function getTargets()
    {
      //return self::CLASS_CONSTRAINT; // error "The constraint cannot be put on properties or getters"
      return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT); // working, but $value is a STRING!!!
    }
 }

My vendor/app/mybundle/Validator/Constraints/CodeValidator.php

<?php
// vendor/app/mybundle/Validator/Constraints/CodeValidator.php

namespace App\Bundle\MyBundle\Validator\Constraints;

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

class CodeValidator extends ConstraintValidator
{
     public function validate($value, Constraint $constraint)
     {
         $value->getId(); // this code not working, because $value is STRING!!
         $this->context->buildViolation($constraint->message)
             ->atPath('code')
             ->addViolation();
     }

}

where I made a mistake?

like image 282
Neokortex Avatar asked Feb 02 '16 21:02

Neokortex


1 Answers

Try to add this to your Constraint :

/**
 * @Annotation
 * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
 */

EDIT

This morning, I took time to try your implementation on a fresh symfony 3 installation.

Also, if you add the @AcmeAssert\Code on a property like the following :

use AppBundle\Validator\Constraints as AcmeAssert;

// ...

/**
 * @var string
 * @AcmeAssert\Code
 * @ORM\Column(name="code", type="string")
 */
private $code;

Only the field will be validated, so $value represents the field value of the property.
For example, if you assign the @AcmeAssert\Code on the $code property in your entity, when the form is submitted, the $value of your validator will represent the field value of your $code property).

If you add the @AcmeAssert\Code on top of your entity like follows :

use AppBundle\Validator\Constraints as AcmeAssert;

/**
 * Foo
 *
 * @ORM\Table(name="foo")
 * @AcmeAssert\Code
 * @ORM\Entity(repositoryClass="AppBundle\Repository\FooRepository")
 */
class Foo

Then, the $value will represents your full entity, and you can make all validation you want by using getters.

I have added my test project in a repository, you can use it to see how use the two alternatives : sf3-constraint-test

In my example, the entity AppBundle::Bar has the constraint on property, and AppBundle::Foo has the constraint on the whole entity.

Hopes it's what you need !

EDIT2

If you are in yaml mapping, use the following for apply the constraint on your whole entity and access to the full object by $value in your constraint :

AppBundle\Entity\AcmeEntity:
    constraints:
        - App\Bundle\MyBundle\Validator\Constraints\Code: ~

On top of your mapping.

And if you want just apply the constraint on one property, and access the value of the field using $value , stay how you are and do your logic on $value which is a string (value of the field corresponding to the entity property constrained in mapping), it's something like :

AppBundle\Entity\AcmeEntity:
    properties:
            # ...
            code:
                - App\Bundle\MyBundle\Validator\Constraints\Code: ~
like image 90
chalasr Avatar answered Oct 11 '22 22:10

chalasr