2015-03-13 64 views
9

我有一个表单定义,它使用了迄今为止最棒的字段类型entity。使用选项query_builder我选择我的值并显示。Symfony2:具有空值的实体表单字段

可悲的是,我需要显示null默认值,如all(这是一个过滤器形式)。我不喜欢选项entity,因为我有数据库值,FormType不应该查询数据库。

我到目前为止的做法是实现一个自定义字段类型,它扩展了entity并在列表顶部添加了一个空条目。字段类型被加载和使用,但不幸的是,虚拟值不被显示。

字段定义:

$builder->add('machine', 'first_null_entity', [ 
    'label' => 'label.machine', 
    'class' => Machine::ident(), 
    'query_builder' => function (EntityRepository $repo) 
    { 
     return $repo->createQueryBuilder('m') 
      ->where('m.mandator = :mandator') 
      ->setParameter('mandator', $this->mandator) 
      ->orderBy('m.name', 'ASC'); 
    } 
]); 

形式类型定义:

class FirstNullEntityType extends AbstractType 
{ 

    /** 
    * @var unknown 
    */ 
    private $doctrine; 

    public function __construct(ContainerInterface $container) 
    { 
     $this->doctrine = $container->get('doctrine'); 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setRequired('query_builder'); 
     $resolver->setRequired('class'); 
    } 

    public function buildView(FormView $view, FormInterface $form, array $options) 
    { 
     $class = $options['class']; 
     $repo = $this->doctrine->getRepository($class); 

     $builder = $options['query_builder']($repo); 
     $entities = $builder->getQuery()->execute(); 

     // add dummy entry to start of array 
     if($entities) { 
      $dummy = new \stdClass(); 
      $dummy->__toString = function() { 
       return ''; 
      }; 
      array_unshift($entities, $dummy); 
     } 

     $options['choices'] = $entities; 
    } 

    public function getName() 
    { 
     return 'first_null_entity'; 
    } 

    public function getParent() 
    { 
     return 'entity'; 
    } 
} 
+0

你可以使用$ choices [''] ='All';在你的表单类型定义 – 2015-03-13 12:10:06

回答

3

另一种方法是使用与从数据库生成选择一个ChoiceList,然后使用在一个自定义选择表单类型,将允许empty_value

选择列表

namespace Acme\YourBundle\Form\ChoiceList; 

use Doctrine\Common\Persistence\ObjectManager; 
use Symfony\Component\Form\Extension\Core\ChoiceList\LazyChoiceList; 
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; 
use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; 

class MachineChoiceList extends LazyChoiceList 
{ 
    protected $repository; 

    protected $mandator; 

    public function __construct(ObjectManager $manager, $class) 
    { 
     $this->repository = $manager->getRepository($class); 
    } 

    /** 
    * Set mandator 
    * 
    * @param $mandator 
    * @return $this 
    */ 
    public function setMandator($mandator) 
    { 
     $this->mandator = $mandator; 

     return $this; 
    } 

    /** 
    * Get machine choices from DB and convert to an array 
    * 
    * @return array 
    */ 
    private function getMachineChoices() 
    { 
     $criteria = array(); 

     if (null !== $this->mandator) { 
      $criteria['mandator'] = $this->mandator; 
     } 

     $items = $this->repository->findBy($criteria, array('name', 'ASC')); 

     $choices = array(); 

     foreach ($items as $item) { 
      $choices[** db value **] = ** select value **; 
     } 

     return $choices; 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    protected function loadChoiceList() 
    { 
     return new SimpleChoiceList($this->getMachineChoices()); 
    } 
} 

选择列表服务(YAML)

acme.form.choice_list.machine: 
    class: Acme\YourBundle\Form\ChoiceList\MachineChoiceList 
    arguments: 
     - @doctrine.orm.default_entity_manager 
     - %acme.model.machine.class% 

自定义表单类型

namespace Acme\YourBundle\Form\Type; 

use Acme\YourBundle\Form\ChoiceList\MachineChoiceList; 
.. 

class FirstNullEntityType extends AbstractType 
{ 
    /** 
    * @var ChoiceListInterface 
    */ 
    private $choiceList; 

    public function __construct(MachineChoiceList $choiceList) 
    { 
     $this->choiceList = $choiceList; 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $choiceList = $this->choiceList; 

     $resolver->setDefault('mandator', null); 

     $resolver->setDefault('choice_list', function(Options $options) use ($choiceList) { 
      if (null !== $options['mandator']) { 
       $choiceList->setMandator($options['mandator']); 
      } 

      return $choiceList; 
     }); 
    } 

    public function getName() 
    { 
     return 'first_null_entity'; 
    } 

    public function getParent() 
    { 
     return 'choice'; 
    } 
} 

自定义表单类型服务(YAML)

acme.form.type.machine: 
    class: Acme\YourBundle\Form\Type\FirstNullEntityType 
    arguments: 
     - @acme.form.choice_list.machine 
    tags: 
     - { name: form.type, alias: first_null_entity } 

表单中的

$builder 
    ->add('machine', 'first_null_entity', [ 
     'empty_value' => 'None Selected', 
     'label'   => 'label.machine', 
     'required'  => false, 
    ]) 
; 
+0

谢谢你的伟大答案。这样,我必须将'MachineChoiceList'和'FirstNullEntityType'注册为服务,并且必须将列表传递给类型,不是吗? – Joshua 2015-03-16 08:43:09

+0

是的,这是正确的。我用这些服务的YAML版本更新了我的答案。 – qooplmao 2015-03-16 10:13:45

+0

谢谢你的帮助。我最终直接在字段类型中构建'ChoiceList',因为它对我来说更加灵活。关键是要按照您的建议扩展“选择”字段。 – Joshua 2015-03-17 10:53:16

4

您可以使用占位符从2.6

+1

占位符doesnt似乎与'query_builder'一起工作 – gondo 2015-10-12 12:51:28

24

这里是Symfony的3.0.3

什么工作

use Symfony\Bridge\Doctrine\Form\Type\EntityType;

$builder->add('example' EntityType::class, array(
    'label' => 'Example', 
    'class' => 'AppBundle:Example', 
    'placeholder' => 'Please choose', 
    'empty_data' => null, 
    'required' => false 
)); 
+2

请注意'empty_data => null'将无法使用ChoiceType – dompie 2017-05-23 15:25:31

相关问题