Help us understand the problem. What is going on with this article?

Symfony Form Events を利用した処理

はじめに

自分の備忘録をかねて、symfonyの機能(特にform)関連をまとめています。
今回は一番便利だけど、なかなか扱いづらいForm Eventsを利用した処理についてまとめていきたいと思います。

今まで書いたsymfonyの記事

今回はform eventsについてまとめたいと思います。

Form Events

symfonyはFormの機能が非常に強力です。
その中でもEvent Dispatcherを利用したForm Eventは実際の実装の上で役立つことが多いと思います。

Event Formの操作 Data タイミング
PRE_SET_DATA Model formを生成した時
POST_SET_DATA Model formを生成し、setDataした時
PRE_SUBMIT Request Data handleRequest時、request dataがmodelに変換される前
SUBMIT Model handleRequest時、request dataがmodelに変換された後
POST_SUBMIT Model handleRequest時、submitが完了した後のタイミングで実行される

 実装例

  • かなり少し無理やりですが下記のような実装のケースを想定してform eventを利用して実装してみます。
  • 本来は正規化を行い子テーブルを持つはずチェックボックスの複数選択肢を、一つのカラムにカンマ区切りで実装する場合

コード

  • Entityは下記のような形、typeカラムにチェックボックスの中にはカンマ区切りで選択された文字列が入る
<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use AppBundle\Validator\Constraint as Custom;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Mapping\ClassMetadata;

/**
 * ToDo.
 *
 * @ORM\Table(name="to_do")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\ToDoRepository")
 */
class ToDo
{

    const TASK_LIST = [
        '1' => 'work',
        '2' => 'hobby',
    ];

    const TYPE_DELIMITER = ',';
    const TYPE_LIST = [
        '1' => 'Hobby',
        '2' => 'Work',
        '3' => 'Study',
    ];

    /**
     * @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 string
     * @ORM\Column(name="type", type="string", length=255, nullable=true)
     */
    private $type;

    /**
     * @var string
     * @ORM\Column(name="date", type="datetime",nullable=false)
     */
    private $date;

    /**
     * @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 int
     */
    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;
    }

    /**
     * @return string
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * @param string $type
     *
     * @return ToDo
     */
    public function setType($type)
    {
        $this->type = $type;

        return $this;
    }

    /**
     * Set memo.
     *
     * @param string $memo
     *
     * @return ToDo
     */
    public function setMemo($memo)
    {
        $this->memo = $memo;

        return $this;
    }

    /**
     * Get memo.
     *
     * @return date
     */
    public function getMemo()
    {
        return $this->memo;
    }

    /**
     * @return date
     */
    public function getDate()
    {
        return $this->date;

        return $this;
    }

    /**
     * @param string $date
     */
    public function setDate($date)
    {
        $this->date = $date;
    }

    /**
     * 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());
    }

    /**
     * taskの表示値を取得
     */
    public function getTaskName()
    {
        $task = $this->getTask();
        return self::TASK_LIST[$task];
    }

    /**
     * typeの表示値を取得
     */
    public function getTypeNames()
    {
        $types = explode(self::TYPE_DELIMITER, $this->getType());
        $typeNames = [];
        foreach ($types as $type) {
            $typeNames[] = self::TYPE_LIST[$type];
        }

        return implode(self::TYPE_DELIMITER, $typeNames);
    }


}
  • Formsは下記のような形、typeカラムにチェックボックスの中にはカンマ区切りで選択された文字列が入る
  • typeのフォームの設定は下記のようになっていて、ChoiceType(選択式)かつ、multiple、expandedをtrueに設定することでチェックボックスの表示になる。
                'type',
                InputType\ChoiceType::class,
                [
                    'choices' => array(
                        '1' => 'Hobby',
                        '2' => 'Work',
                        '3' => 'Study',
                    ),
                    'multiple' => true,
                    'expanded' => true,
                ]
  • FormEventsの実際の設定はbuildFormの中でaddEventListenerを行うことで設定する。functionの中でそのeventの中でファンクションを呼び出し、変換した値をentityにセットし直しています。
        $builder
            ->addEventListener(
                FormEvents::PRE_SET_DATA,
                function (FormEvent $event) {
                    $form = $event->getForm();
                    $entity = $event->getData();
                    $convertedType = $this->convertValueToArr($entity->getType());
                    $entity->setType($convertedType);
                }
            )
            ->addEventListener(
                FormEvents::POST_SUBMIT,
                function (FormEvent $event) {
                    $entity = $event->getData();
                    $convertedType = $this->parseArrToStr($entity->getType());
                    $entity->setType($convertedType);
                }
            );
    }


    public function convertValueToArr($value)
    {
        return explode(',', $value);
    }

    public function parseArrToStr($type)
    {
        return implode(',', $type);
    }
yutachaos
Programmer,Bassist,Bibliomania
recruitmp
結婚・カーライフ・進学の情報サイトや『スタディサプリ』などの学びを支援するサービスなど、ライフイベント領域に関わるサービスを提供するリクルートグループの中核企業
http://www.recruit-mp.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした