LoginSignup
12
11

More than 5 years have passed since last update.

Symfony2でFormTypeからContainerを参照する

Posted at

前回はEntityRepositoryからContainerを参照できるようにしました。
今回はFormTypeからContainerを参照できるようにします。

環境

Symfony 2.3.17

実装する

Containerを参照可能なFormTypeクラスを作成

AbstractContainerAwareType.php
<?php

namespace Some\MyBundle\Component\Form;

use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Form\AbstractType;

abstract class AbstractContainerAwareType extends AbstractType implements ContainerAwareInterface
{
    /**
     * Container
     * @var ContainerInterface
     */
    protected $container;

    /**
     * {@inheritdoc}
     */
    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }

    /**
     * Get Container
     * @return ContainerInterface
     */
    public function getContainer()
    {
        return $this->container;
    }
}

AbstractContainerAwareTypeにContainerを設定するFormFactoryクラスを作成

MyFormFactory.php
<?php

namespace Some\MyBundle\Component\Form;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Form\FormFactory;
use Symfony\Component\Form\FormRegistryInterface;
use Symfony\Component\Form\ResolvedFormTypeFactoryInterface;

class MyFormFactory extends FormFactory
{
    /**
     * Container
     * @var ContainerInterface
     */
    private $container;

    /**
     * @param FormRegistryInterface $registry
     * @param ResolvedFormTypeFactoryInterface $resolvedTypeFactory
     * @param ContainerInterface $container
     */
    public function __construct(FormRegistryInterface $registry, ResolvedFormTypeFactoryInterface $resolvedTypeFactory, ContainerInterface $container)
    {
        parent::__construct($registry, $resolvedTypeFactory);
        $this->container = $container;
    }

    /**
     * {@inheritdoc}
     */
    public function createNamedBuilder($name, $type = 'form', $data = null, array $options = array())
    {
        if ($type instanceof AbstractContainerAwareType) {
            $type->setContainer($this->container);
        }

        return parent::createNamedBuilder($name, $type, $data, $options);
    }
}

サービスに登録

services.yml
services:
    form.factory: # FrameworkBundleで定義されているものを再定義
        class: Some\MyBundle\Component\Form\MyFormFactory
        arguments: [ @form.registry, @form.resolved_type_factory, @service_container ]

使用する

AbstractContainerAwareTypeを継承したクラス内で$this->getContainer()するとContainerを参照できます。

SomeType.php
<?php

namespace Some\MyBundle\Form\Type;

use Some\MyBundle\Component\Form\AbstractContainerAwareType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class SomeType extends AbstractContainerAwareType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $container = $this->getContainer();

        $builder
            ->add('someColumn', 'choice', [
                'choices' => $container->getParameter('some.parameter'),
            ])
        ;

        $logger = $container->get('logger');
        $logger->debug('FormTypeからログ出力!');
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver
            ->setDefaults([
                'data_class' => 'Some\MyBundle\Entity\SomeTable',
            ])
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'some';
    }
}
12
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
11