Edited at

symfony validation処理の方法


はじめに

案件でとりあえず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で弾かれなくて汗かいた)

http://symfony.com/doc/current/reference/constraints/GreaterThan.html



->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