В соответствии с этой статьей в документах Symfony я создал настраиваемый тип поля, настроил его в services.yml
, и я могу использовать его успешно.
Например, я создаю собственное поле с именем customdate
следующим образом, которое отлично работает:
# src/Acme/DemoBundle/Resources/config/services.yml services: acme_demo.form.type.date: class: Acme\DemoBundle\Form\Type\DateType tags: - { name: form.type, alias: customdate }
Однако, если я попытаюсь назвать свое настраиваемое поле как date
(это то же самое, что и существующий тип поля Symfony , так как это то, что я пытаюсь переопределить), как показано ниже, тогда Symfony полностью игнорирует мое настраиваемое поле и по умолчанию вместо этого используется встроенный тип поля date
Symfony:
# src/Acme/DemoBundle/Resources/config/services.yml services: acme_demo.form.type.date: class: Acme\DemoBundle\Form\Type\DateType tags: - { name: form.type, alias: date }
Я проверил, что моя getName()
возвращает правильное имя, совпадающее с псевдонимом, который я предоставил в services.yml
.
Ниже приведен код, в котором я использую вышеуказанные услуги.
Это работает:
public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('date', 'customdate'))); }
Это не работает: (или, скорее, Symfony использует встроенный тип поля вместо моего)
public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('date', 'date'))); }
Я должен отметить, что если я заменил «customdate» или «date» на созданный вручную объект, такой как new Date()
тогда он отлично работает. Проблема заключается в том, что Symfony предпочитает свои встроенные типы полей над теми, которые указаны в services.yml
.
Мой вопрос: есть ли способ переопределить встроенные типы полей Symfony с настраиваемыми типами полей, которые имеют одинаковое имя? Очевидно, что из того, что я описал выше, Symfony, похоже, игнорирует любые настраиваемые поля, которые сглажены с тем же именем, что и встроенный тип поля Symfony. Есть ли способ обойти это?
Насколько я знаю, нет способа действительно переопределить типы базового поля, вы можете наследовать их и использовать свое собственное имя.
Однако, если тип поля, который вы хотите переопределить, не обеспечивает функциональность, которая, по вашему мнению, должна быть проблемой с этим типом, о котором следует сообщить.
Для вашего случая тип даты не принимает типичную строку формата php date (). Изучая документацию, мы видим, что формат даты анализируется классом IntlDateFormatter. Для правильных форматов ознакомьтесь с этим списком .
Чтобы выполнить формат, который вам нужен, date('d M Y')
вы должны использовать:
$builder->add('my_date_field', 'date', array( 'format'=>'d MMM Y' ));
Чтобы ответить на первый вопрос, есть способ переопределить встроенные типы форм symfony. Вышеприведенный код почти правильный. Просто нужно использовать тот же идентификатор службы, что и в symfony. См. Конфигурацию службы Symfony и используйте один и тот же служебный идентификатор:
# src/Acme/DemoBundle/Resources/config/services.yml services: form.type.date: class: Acme\DemoBundle\Form\Type\DateType tags: - { name: form.type, alias: date }
Я протестировал это и, похоже, работает нормально. Acme\DemoBundle\Form\Type\DateType
должен расширять класс Symfony\Component\Form\Extension\Core\Type\DateType
с любыми изменениями. Это можно сделать с помощью любого типа формы Symfony.
Другой подход несколько более сложный, но более надежное будущее – это использование прошивки для изменения класса определения службы, но остальное без изменений. Это выглядит как:
//src/Acme/DemoBundle/DependencyInjection/Compiler/OverrideServiceCompilerPass.php namespace Acme\DemoBundle\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; class OverrideServiceCompilerPass implements CompilerPassInterface { public function process(ContainerBuilder $container) { $definition = $container->getDefinition('form.type.date'); $definition->setClass('Acme\DemoBundle\Form\Type\DateType'); } }
как//src/Acme/DemoBundle/DependencyInjection/Compiler/OverrideServiceCompilerPass.php namespace Acme\DemoBundle\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; class OverrideServiceCompilerPass implements CompilerPassInterface { public function process(ContainerBuilder $container) { $definition = $container->getDefinition('form.type.date'); $definition->setClass('Acme\DemoBundle\Form\Type\DateType'); } }
то пропуск компилятора зарегистрирован в классе AcmeDemoBundle, например;
// src/Acme/DemoBundle/AcmeDemoBundle.php namespace Acme\DemoBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\DependencyInjection\ContainerBuilder; use Acme\DemoBundle\DependencyInjection\Compiler\OverrideServiceCompilerPass; class AcmeDemoBundle extends Bundle { public function build(ContainerBuilder $container) { parent::build($container); $container->addCompilerPass(new OverrideServiceCompilerPass()); } }
Дополнительную информацию см. В разделе « Предоставление дополнительных документов doc и компилятора» .