I work with symfony 2.8.3.

I read these resources here:
- How to Create a Custom Form Field Type
- Symfony2: Overriding a custom field type with a custom field and many others, since it was presented in these sources (I can't post a lot of links).

It is necessary to create this type of date field, because it would meet the requirements of the customer in many ways, incl. and date format. Moreover, this (my, new) type should be used everywhere (!!) in the project, even with third-party bundles.

I create a class:

class DateType extends \Symfony\Component\Form\Extension\Core\Type\DateType { // тут переопределяю нужные мне методы } 

I register it in the service:

 services: #... form.type.date: class: Application\Symfony\Component\Form\Extension\Core\Type\DateType tags: - { name: form.type, alias: date } #... 

and use in the form of:

 public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('birthday', 'date', array( 'widget' => 'single_text', 'label' => 'form.label.birthday', 'translation_domain' => $this->translation_domain, 'required' => true, 'invalid_message' => 'form.error.birthday', 'attr' => array( 'class' => 'datepicker without-error-text', ), 'format' => 'dd-MM-yyyy', )); } 

However, this code throws an exception:

The field type "Symfony \ Component \ Form \ Extension \ Core \ Type \ DateType" is not registered with the service container.

How not registered? !! And yes, it is not registered. I register my type instead of the built-in one.

In one of the answers in the question, the link to c. I cited earlier, it was advised to forcibly register your type by interfering with the operation of the dependency compiler.

Ok, do.

I create my own compiler:

 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'); } } 

I use it when building the main bundle:

 // 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()); } } 

However, it does not bring me success. Again I get an exception, the truth is different:

The type name is not specified for the service "form.type.date". Expected "Symfony \ Component \ Form \ Extension \ Core \ Type \ DateType", given "Application \ Symfony \ Component \ Form \ Extension \ Core \ Type \ DateType"

As the code study showed, the Sonata-project throws an exception from different bundles. In the project, I use their admin panel and their blocks. Those. that they cannot create a date field because they stumble upon the difference in the names of classes.

Tell me, plz, what am I missing or doing wrong?

Thank.

PS Most please do not ask why I need this or that. If you can help / help, help / tell me. No - better keep silent.

Pss thanks again.

    1 answer 1

    The problem is in the SonataAdminBundle . There are specific hardcoded values ​​for standard types. Developers can understand: they did not even think that someone would like to change the standard symphony types.

    To turn your tricky business, you need to override the mapping of standard types, as well as the Sonat type DatePicker (if you use it, of course), which explicitly refers to the symphony type of date.

    Redefining Type Mapping

    This can be done in two ways:

    Through config:

     # app/config/config.yml sonata_admin: form: mapping: type: date: 'Acme\DemoBundle\Form\Type\DateType' 

    Through explicit loading in the code:

    To do this, you need to call the method at any time after downloading the Sonatovsky bandl:

     Sonata\CoreBundle\Form\FormHelper::registerFormTypeMapping( ['date' => 'Acme\DemoBundle\Form\Type\DateType'] ); 

    This method is more convenient if you still need to sometimes let the sonata get loose.

    Redefining Sonatov's DatePicker Type

    Again we climb into the compiler pass and overwrite the class value for the service:

     // src/Acme/DemoBundle/DependencyInjection/Compiler/OverrideServiceCompilerPass.php $definition = $container->getDefinition('sonata.core.form.type.date_picker'); $definition->setClass('Acme\DemoBundle\Form\Type\DatePickerType'); 

    Do not forget to create this class as well:

     // src/Acme/DemoBundle/Form/Type/DatePickerType.php class DatePickerType extends Sonata\CoreBundle\Form\Type\DatePickerType { public function getParent() { return method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix') ? 'Acme\DemoBundle\Form\Type\DateType' : // Тут должен быть FQCN Вашей реализации типа 'date' // SF <2.8 BC ; } }