Symfony logo

Extend Symfony form validation capabilities with ExpressionLanguage component

Form validation server side is probably one of the most important thing in a web application. In this article, I will explain how Symfony ExpressionLanguage component can be used to save you a lot of time avoiding to use custom validators.

Installation

This component, added in Symfony 2.4, is required by the Validation component so no extra installation is required. The code please.

Use case

We will assume a model which has a start date and an end date. The end date is optional but we want it to be greater or equal to the start date. Here is the entity :

<?php
// src/AppBundle/Entity/Entity.php
namespace AppBundle\Entity;

class Entity
{
    /**
     * @var int
     */
    protected $id;

    /**
     * @var \DateTime
     */
    protected $startDate;

    /**
     * @var \DateTime|null
     */
    protected $endDate;

    /**
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @return \DateTime
     */
    public function getStartDate()
    {
        return $this->startDate;
    }

    /**
     * @param \DateTime $startDate
     */
    public function setStartDate($startDate)
    {
        $this->startDate = $startDate;
    }

    /**
     * @return \DateTime|null
     */
    public function getEndDate()
    {
        return $this->endDate;
    }

    /**
     * @param \DateTime|null $endDate
     */
    public function setEndDate(\DateTime $endDate = null)
    {
        $this->endDate = $endDate;
    }
}

Now, we will use XML to validate our entity as requested :

<!-- src/AppBundle/Resources/config/validation/Entity.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">

    <class name="AppBundle\Entity\Entity">
        <property name="startedOn">
            <constraint name="Date" />
            <constraint name="NotNull" />
        </property>

        <property name="endedOn">
            <constraint name="Date" />
            <constraint name="Expression">
                <option name="expression">null == this.getEndedOn() || this.getEndedOn() >= this.getStartedOn()</option>
            </constraint>
        </property>
    </class>
</constraint-mapping>

THE END.

But you might want a bit of explanation :
In the validation process, you can access your object using the this keyword. The ExpressionLanguage component will allow you to access any of the object methods. We first check that an end date has been provided and if so, we check it is greater or equal to the start date value.

The validation has been attached to the endedOn property to ease error reporting. However, you can use it at the class level.

This solution will allow you to avoid to write a new custom validator, probably in most of the cases.

Related links

2 thoughts on “Extend Symfony form validation capabilities with ExpressionLanguage component”

    1. That’s a possible behavior but the purpose of this post was solely to explain the technical part. I guess this is something you can implement on your own with the explanations 😉

Leave a Reply

Your email address will not be published. Required fields are marked *