We can define form validation constraints with annotations in entities, directly in formtypes or in model classes. In this example we're going to use formtypes to handle validations.


Entity


namespace Football\FrontendBundle\Entity;

use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

/**
* @ORM\Entity(repositoryClass="Football\FrontendBundle\Repository\CountryRepository")
* @ORM\Table(name="country")
* @UniqueEntity(fields="code", message="Country code is already taken.")
* @UniqueEntity(fields="name", message="Country name is already taken.")
* @ORM\HasLifecycleCallbacks
*/
class Country
{
/**
* @ORM\Id
* @ORM\Column(type="smallint")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;

/**
* @ORM\Column(type="string", length=2, unique=true)
*/
protected $code;

/**
* @ORM\Column(name="name", type="string", length=100, unique=true)
*/
protected $name;
}

FormType


namespace Football\FrontendBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Regex;

class CountryType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options = [])
{
$builder
->setMethod($options['method'])
->setAction($options['action'])
->add(
'code',
'text',
[
'error_bubbling' => true,
'constraints' => [
new NotBlank(
[
'message' => 'Country code is required.'
]
),
new Regex(
[
'pattern' => '/^[A-Z]{2}$/',
'message' => 'Country code must be exactly 2 character long upper case letters.'
]
)
]
]
)
->add(
'name',
'text',
[
'error_bubbling' => true,
'constraints' => [
new NotBlank(
[
'message' => 'Country name is required.'
]
),
new Length(
[
'max' => 100,
'maxMessage' => 'Country name cannot be longer than {{ limit }} characters.'
]
)
]
]
);
}

public function getName()
{
return 'country';
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
['data_class' => 'Football\FrontendBundle\Entity\Country']
);
}
}

Twig template


{% extends 'FootballFrontendBundle:Country:index.html.twig' %}

{% block body %}
{% spaceless %}
{{ parent() }}
COUNTRY - Create
<hr />
{{ form_start(form, { attr: {novalidate: 'novalidate'} }) }}
{% if form_errors(form) != '' %}

{{ form_errors(form) }}

{% endif %}

<p>CODE: {{ form_widget(form.code) }}</p>
<p>NAME: {{ form_widget(form.name) }}</p>

<p><button name="button">Submit</button></p>
{{ form_end(form) }}
{% endspaceless %}
{% endblock %}