Contributed by
Christian Flothmann
in #24530.

Form type extensions allow you to modify any existing form field types. They are used to add a specific feature to a single form type (e.g. adding a "download" feature to the FileType field type) and to add a generic feature to several field types at once.

In Symfony 4.2 we've improved form type extensions to simplify their config and to allow them to extend multiple types.

简化的配置

In previous Symfony versions, Form type extensions define the getExtendedType() method to tell which form type they are extending:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace App\Form\Extension;
 
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\FileType;
 
class ImageTypeExtension extends AbstractTypeExtension
{
    // ...
 
    public function getExtendedType()
    {
        return FileType::class;
    }
}

Before using them, you had to register those classes as services and apply the form.type_extension service tag to them. Unfortunately, you also needed to repeat the extended form type in the service declaration:

1
2
3
4
5
6
7
8
# config/services.yaml
services:
    # ...

    App\Form\Extension\ImageTypeExtension:
        tags:
            - { name: form.type_extension,
                extended_type: Symfony\Component\Form\Extension\Core\Type\FileType }

This repetition is cumbersome, so we improved it and in Symfony 4.2, form type extensions no longer require any service configuration. First, replace the getExtendedType() method by a new static method called getExtendedTypes():

1
2
3
4
5
6
7
8
9
class ImageTypeExtension extends AbstractTypeExtension
{
    // ...
 
    public static function getExtendedTypes(): iterable
    {
        return [FileType::class];
    }
}

Second, if the app has enabled the service autoconfiguration feature, Symfony will apply the form.type_extension tag automatically to any service whose class implements FormTypeExtensionInterface::class.

Thanks to the new static method and the automatic tag, you no longer need to configure anything for your form type extensions. Creating the form type extension class is all you need to do.

继承多个表单类型

A side improvement provided by the new getExtendedTypes() method is that you can now extend multiple types with a single extension class, instead of having to create one extension class per form type.

The value returned by this method is of type iterable, so you can return a traditional array or be more creative if needed:

1
2
3
4
5
6
7
8
9
10
11
class DateTimeExtension extends AbstractTypeExtension
{
    // ...
 
    public static function getExtendedTypes(): iterable
    {
        yield DateTimeType::class;
        yield DateType::class;
        yield TimeType::class;
    }
}

Not implementing the static getExtendedTypes() method when implementing FormTypeExtensionInterface is deprecated since Symfony 4.2. The method will be added to the interface in 5.0.