Posted at

Symfony2でFormTypeからContainerを参照する

More than 5 years have passed since last update.

前回は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';
}
}