2015-03-13 73 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

相關問題