New in Symfony 5.1: Deprecate public services into private services

Warning: This post is about an unsupported Symfony version. Some of this information may be out of date. Read the most recent Symfony Docs.

Contributed by
Thomas Calvet
in #36470.

One of the key features that makes developers love Symfony is the handling of deprecated features. Symfony's backward compatibility promise ("BC promise") ensures that your application will never break when upgrading between minor versions.

In Symfony 5.1 we introduced a new way to deprecate public services and turn them into private while keeping that BC promise.

In practice, this features require adding a service tag called container.private and a couple of tag attributes that define the package and version where it was deprecated:

        # ...
        public: true
            - { name: 'container.private', package: 'foo/bar', 'version': '1.2' }

If your application tries to get that service directly from the container ($container->get('foo')) you'll see the following error:

Since foo/bar 1.2: Accessing the "foo" service directly from the container
is deprecated, use dependency injection instead.

Technically this feature uses a compiler pass to create a deprecated public alias of the public service. This is done only when the code access the service directly (not when using autowiring) to avoid displaying unnecessary deprecations.

We're already using this feature in Symfony core to turn some public services into private (e.g. the twig service in PR #36739) and you can also start using it in your own public bundles and private applications.

Help the Symfony project!

As with any Open-Source project, contributing code or documentation is the most common way to help, but we also have a wide range of sponsoring opportunities.


That configuration does not say anything about the deprecation of the service. It really should contain the word "deprecated" somewhere to make the meaning clear and explicit. The concept itself seems to be sound, but DX could be better.
@Josef this feature does not deprecate the service. It prepares it to become a private service in the next major version. The service itself is not deprecated (there is another feature for that already).
@Christophe you are right, but I think that @Josef means that you see the tag name "container.private" and you don't understand immediately its purpose. It's not self-explanatory. However, given that this is a "niche" and "advanced" feature, it may be OK.
Maybe something like container.deprecate_public would be a bit more exlicit

Comments are closed.

To ensure that comments stay relevant, they are closed for old posts.