Skip to content

[RFC][OptionsResolver] Add ability to deprecate options #27216

Closed
@yceruto

Description

@yceruto

Introduction

Currently the consumers of the OptionsResolver component (mainly the Form component, later LDAP started to use it and possibly many bundles and libraries too) need sometime to delete or rename an already defined option or change its default value keeping BC, seeing itself in the need to create notes like this:

'property' => null, // deprecated, use "choice_label"

and manage themselves where and how to trigger the corresponding depreciation message:

// deprecation note
$propertyNormalizer = function (Options $options, $propertyName) {
if ($propertyName) {
@trigger_error('The "property" option is deprecated since Symfony 2.7 and will be removed in 3.0. Use "choice_label" instead.', E_USER_DEPRECATED);
}
return $propertyName;
};

Moreover, it isn't always effective if the option has a default value. For instance, according to the previous code doing this:

$builder->add('foo', EntityType::class, [
    // ...
    'property' => null,
]);

it wouldn't show the deprecation message because when the configured default value is equal to the given value -> we don't know that this option is being used. Also, the normalizer function (as just one is allowed) can be overridden by any current child type or type extension in userland, in that case, the message wouldn't show either.

Proposal to improve the current scenario

Introduce a simpler and safer way to deprecate an option using a new method in OptionsResolver:

public function setDeprecated(string $option, string $deprecationMessage = 'The option "%name%" is deprecated.', callable $callback = null): self

Then, if this option is used or has default value, the deprecation message always will be triggered. Conditionally you could deprecate some values of many feasible by using the 3rd argument.

It is a small but powerful feature as this information can be displayed anywhere, in the form profiler, debug:form command, etc.

Other method that could help to know whether a given option is deprecated or not is:

public function isDeprecated(string $option): bool

Example

Deprecating a whole option:

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults([
        'property' => null,
        'choice_label' => // ...
    ]);

    $resolver->setDeprecated('property', 'The option "property" is deprecated since Symfony X.Y. Use "choice_label" instead.');
}

Deprecating an option value:

public function configureOptions(OptionsResolver $resolver)
{
    $resolver
        ->setDefault('foo', false)
        ->setAllowedTypes('foo', ['null', 'bool'])
        ->setDeprecated('foo', 'Passing "null" to option "foo" is deprecated since ...', function ($value) {
            return null === $value; // value before normalization
        })
    ;
}

Let me know first if it's something that core & community need. I've prepared a tiny PR for that.

Cheers!

Metadata

Metadata

Assignees

No one assigned

    Labels

    OptionsResolverRFCRFC = Request For Comments (proposals about features that you want to be discussed)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions