はじめに
案件でとりあえずsymfony使い始めたけど、情報がまばらで苦労してます。
自分の復習や備忘録も兼ねてのsymfony記事です。
今回はvalidationについてまとめようと思います。
一個目のformの記事
http://qiita.com/yutaChaos/items/0ae0d1797db4cb16466c
環境
- symgony 2.8
- php 7.0
validationについて
- symfonyでのvalidationは大きく分けて2つあります。(僕が現時点で知っているやつですが)
- entityに直接記述する
- FormTypeに記述する
entityに直接記述する方法
今回使用するentityの基本コードはこれです。
ToDo.php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* ToDo
*
* @ORM\Table(name="to_do")
* @ORM\Entity(repositoryClass="AppBundle\Repository\ToDoRepository")
*/
class ToDo
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="task", type="integer", length=1)
*/
private $task;
/**
* @var string
* @Assert\NotBlank()
* @Assert\Length(min = 2,max = 255)
* @ORM\Column(name="memo", type="string", length=255, nullable=true)
*/
private $memo;
/**
* @var \DateTime
*
* @ORM\Column(name="r_datetime", type="datetime", nullable=true)
*/
private $rDatetime;
/**
* @var \DateTime
*
* @ORM\Column(name="u_datetime", type="datetime", nullable=true)
*/
private $uDatetime;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set task
*
* @param string $task
* @return ToDo
*/
public function setTask($task)
{
$this->task = $task;
return $this;
}
/**
* Get task
*
* @return string
*/
public function getTask()
{
return $this->task;
}
/**
* Set memo
*
* @param string $memo
* @return ToDo
*/
public function setMemo($memo)
{
$this->memo = $memo;
return $this;
}
/**
* Get memo
*
* @return string
*/
public function getMemo()
{
return $this->memo;
}
/**
* Set rDatetime
*
* @param \DateTime $rDatetime
* @return ToDo
*/
public function setRDatetime($rDatetime)
{
$this->rDatetime = $rDatetime;
return $this;
}
/**
* Get rDatetime
*
* @return \DateTime
*/
public function getRDatetime()
{
return $this->rDatetime;
}
/**
* Set uDatetime
*
* @param \DateTime $uDatetime
* @return ToDo
*/
public function setUDatetime($uDatetime)
{
$this->uDatetime = $uDatetime;
return $this;
}
/**
* Get uDatetime
*
* @return \DateTime
*/
public function getUDatetime()
{
return $this->uDatetime;
}
/**
* @ORM\PrePersist
*/
public function refreshRDatetime()
{
$this->setRDatetime(new \Datetime());
}
/**
* @ORM\PrePersist
* @ORM\PreUpdate
*/
public function refreshUDatetime()
{
$this->setUDatetime(new \Datetime());
}
}
- $memoにNotBlankとLengthの制約をかけるためにannotationを付与しています。
これだけです。めっちゃ簡単。optionを設定する場合は@Assert\Length(min = 2,max = 50)
のように引数に値を付与すれば設定ができます。
/**
* @var string
* @Assert\NotBlank()
* @Assert\Length(min = 2,max = 255)
* @ORM\Column(name="memo", type="string", length=255, nullable=true)
*/
private $memo;
FormTypeに記述する
次にFormTypeに記載する場合です。
ToDoType
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type as InputType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints as Assert;
class ToDoType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('task',
InputType\ChoiceType::class,
[
'choices' => [
'1' => 'work',
'2' => 'hobby'
],
'constraints' =>
[
new Assert\NotBlank()
]
]
)
->add('memo',
InputType\TextareaType::class,
[
'constraints' => [
new Assert\NotBlank(),
new Assert\Length(['min' => 2, 'max' => 255])
]
]);
$entity = $builder->getData();
if(!$entity->getId()){
$builder->add('Create', InputType\SubmitType::class,
[
'attr' => [
'class' => 'btn btn-primary'
]
]
);
}else{
$builder->add('Edit', InputType\SubmitType::class,
[
'attr' => [
'class' => 'btn btn-primary'
]
]
);
}
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\ToDo'
));
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_todo';
}
}
ここではentityと同じvalidationルール(NotBlank,Length)を書いています。
add
関数は第1引数がentityのメンバーの名前、第2引数はそのメンバーで利用したいフォームの種類、そして第3引数にはoptionが設定できます。
Entityと同様のvalidationはFormTypeでのvalidationは第三引数に配列キーをconstraintsで渡すことで設定できます。
ただEntityに記載する場合と異なるのが、FormTypeは実際に生成されるFormの情報を記載しているので、
制約だけではなく、入力フォームの種類も記載できます。
第二引数ではTextareaType
を渡していますが、この情報を持ったFormを実際に表示するとtestareaのフォームが表示されます。
それだけではなく、formの種類に寄ったvalidationも自動的に付与されます。
例えば NumberType
をフォームの種類を設定した場合は数字以外を弾くvalidationが設定されます。
FormTypeで規定する場合は適切なFormの種類を設定した上でconstraintsを設定することを考えると幸せになれると思います。
(前にTextTypeにGreaterThanを設定したら、普通の文字列がvalidationで弾かれなくて汗かいた)
->add('memo',
InputType\TextareaType::class,
[
'constraints' => [
new Assert\NotBlank(),
new Assert\Length(['min' => 2, 'max' => 255])
]
])
終わりに
symfonyには強力なvalidation機能が備わっていて、標準のvalidationでも結構いろいろなことができます。
さらに自分でカスタムvalidationを作成して、付与することが出来ます。
entityでもvalidation書けるけど、やっぱりEntityはデータ構造や付随する情報ぐらいにとどめて、実際のvalidationはFormTypeに任せた方がいいかなーと現時点では思っています。
(Best Practice読んでもValidation周りはよくわからんかった。。。)
参考
http://symfony.com/doc/current/reference/constraints.html
http://symfony.com/doc/current/reference/forms/types.html
http://symfony.com/doc/current/form/events.html