У меня есть определение формы, в котором используется entity
большим полем типа. С помощью опции query_builder
я выбираю свои значения, и они отображаются.
Грустная часть, я должен показать null
значение по умолчанию, как и all
(это форма фильтра). Мне не нравится опция choices
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'; } }
Альтернативным подходом было бы использовать 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, ]) ;
Вот что работает в 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 ));
Вы можете использовать placeholder от 2.6