6
votes

I'm working in a bundle where the user creates a "comision" using a form, and I'm trying to check that the user still have "credit". So I created a custom validator that queries past comisions and throws an error if credit is not enough.

My problem is that if the user submits a date with a wrong format in the "date" field (i.e. 32-13-20122 24:05) Symfony still tries to run my custom validation and I get all sort of errors (because $comision->getDate() is null and not a valid DateTime object).

I'm getting this error:

clone method called on non-object

I can also check if value of $comision->getDate() is a valid datetime in my custom validator, but it seems to me that it should be not necessary since I added this rules in the date property.

This is my entity (simplified)

/**
 * @MyValidation\TotalHours()
 */
class Comision
{

/**
 * @ORM\Column(type="datetime")
 * @Assert\DateTime()
 * @Assert\NotNull()
 */
protected $date;


/**
 * @ORM\Column(type="decimal", nullable=false, scale=1)
 * @Assert\NotBlank()
 */
protected $hours;

...

My form class ...

class NewComisionType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
            $builder
                ->add('date', DateTimeType::class, array(
                'widget' => 'single_text',
                'label' => 'Starting date and time',
                'format' => 'dd/MM/yyyy HH:mm'
                ))
                ->add('hours', ChoiceType::class, array(
                    'label'=> 'How many hours',
                    'choices' => array(
                        '1:00' => 1,
                        '1:30' => 1.5,
                        '2:00' => 2,
                        '2:30' => 2.5,
                        '3:00' => 3
                    )
                ))
...

And my cutom validator that checks past comisions to find if user still has "credit"

public function validate($comision, Constraint $constraint)
{
$from = clone $comision->getDate();
$from->modify('first day of this month');

$to = clone $comision->getDate();
$to->modify('last day of this month');

$credit = $this->em->getRepository("ComisionsBundle:Comision")->comisionsByDate($comision,$from, $to);

...
3
Why dont you add validation for date? symfony.com/doc/current/reference/constraints/Date.html Or maybe in your custom validatorkunicmarko20
I did (i'm editing my question to add it) but it has no effect. It seems that it runs all the validation rules even if no valid datetime after data-transform.Diego Montero

3 Answers

4
votes

One way would be to group your constraints as described in the docs.

This way your can define two groups of contraints whereas the second group will be validated only if all constraints in the first group are valid.

Regarding your use case, you could put your custom constraint in a different group than the default one to be sure your have a proper $comision DateTime object.

1
votes

To do this, you can use the GroupSequence feature. In this case, an object defines a group sequence, which determines the order groups should be validated.

https://symfony.com/doc/current/validation/sequence_provider.html

The solution should look like this:

/**
 * @MyValidation\TotalHours(groups={"Strict"})
 * @Assert\GroupSequence({"Comision", "Strict"})
 */
class Comision

In this way, it will first validate all constraints in the group Comision (which is the same as the Default group). Only if all constraints in that group are valid, the second group, Strict, will be validated, making sure $comision->getDate() will have a DateTime instance.

0
votes

IIRC data transformers run before validation, you can go with data transformer for your date:

https://symfony.com/doc/current/form/data_transformers.html

and then in data transformer check if the date is valid and if not throw an error.