Chi
Chi

Reputation: 1410

Symfony2: access raw form data in validator

I created my own validator for a Symfony2 form. It's called ValidDateValidator and it's supposed to filter out invalid dates, such as 2015-02-31. The form type looks like this:

->add(
        'thedate',
        DateType::class,
        array(
            'widget' => 'single_text',
            'format' => 'yyyy-MM-dd',
            'constraints' => array(
                new ValidDate()
            )
        )
)

now if I try to access this in my validator like this:

public function validate($value, Constraint $constraint){
    //this returns 2015-03-03 
    echo $value->format('Y-m-d'); 
}

I get "2015-03-03" as a result. Is there a way to access the raw form data without them being processed?

Upvotes: 4

Views: 961

Answers (2)

Emanuel Oster
Emanuel Oster

Reputation: 1306

Unfortunately this is not possible. Validators receive their data after the data transformation.

What you can do is to create your own view transformer and use that instead of the standard one. The view transformer takes the input data and transforms it into the norm data. In the case of a DateField this is just the DateTime-Object.

You can throw an exception during this transformation, which would result in an form error. More specifically, it would display the invalid_message from your DateField.

Let me try to give you an example:

The transformer:

namespace AppBundle\Form\DataTransformer;

use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

class StringToDateTransformer implements DataTransformerInterface
{  
    /**
     * Transforms a DateTime object to a string .
     *
     * @param  DateTime|null $date
     * @return string
     */
    public function transform($date)
    {
        if (null === $date) {
            return '';
        }

        return $date->format('Y-m-d');
    }

    /**
     * Transforms a string to a DateTime object.
     *
     * @param  string $dateString
     * @return DateTime|null
     * @throws TransformationFailedException if invalid format/date.
     */
    public function reverseTransform($dateString)
    {
        //Here do what ever you would like to do to transform the string to 
        //a DateType object
        //The important thing is to throw an TransformationFailedException
        //if something goes wrong (such as wrong format, or invalid date):

        throw new TransformationFailedException('The date is incorrect!');

        return $dateTime;
    }
}

In your form builder:

$builder->get('thedate')
            //Important!
            ->resetViewTransformers()
            ->addViewTransformer(new StringToDateTransformer());

Note the resetViewTransformers() call. Some fields such as DateTypealready have a view transformer. By calling this method, we get rid of this default transformer, causing only our transfomrer to be called.

Upvotes: 2

DevDonkey
DevDonkey

Reputation: 4880

its the \DateTime::format converting the extra days into the new date. Not the data coming from the form.

You can use checkdate to see if you have valid components like this.

$dateString = '2015-2-31';

$bits = explode('-', $dateString); // split the string
list($y, $m, $d) = $bits; // variablise the parts

if(checkdate($m, $d, $y)) {
    // do something
} else {
    // do something else
}

example

Upvotes: 1

Related Questions