Symfony Form Events を利用した処理

  • 0
    いいね
  • 0
    コメント

    はじめに

    自分の備忘録をかねて、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に設定することでチェックボックスの表示になる。
      php
      '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);
        }