SymfonyWorld Online 2021 Winter Edition December 9 – 10, 2021 100% Online 25 talks and 10 workshops

New in Symfony 4.2: Important deprecations

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

Symfony's Backward Compatibility Promise ensures smooth upgrades in your projects because it forbids backward compatibility breaks in minor releases. Instead of changing or removing existing features, we mark them as deprecated and change them in the next major Symfony version.

The document explains all deprecations in details and you'll see them too in the Web Debug Toolbar, the profiler and when running tests. This article summarizes the most important deprecations so you can start upgrading your Symfony 4 apps.

Deprecated a template directory

Contributed by
Yonel Ceruto
in #28891.

Storing the app templates in src/Resources/views/ is now deprecated. You must store them in the directory defined in the twig.default_path config option in config/packages/twig.yaml, which is templates/ by default.

Deprecated the Kernel name and the root dir

Contributed by
Fabien Potencier
in #28809 and #28810.

The KernelInterface::getName() method and the parameter have been deprecated. There's no alternative to them because this is a concept that no longer makes sense in Symfony applications.

If you need a distinctive ID for the kernel of the application, you can use the KernelInterface::getContainerClass() method and the kernel.container_class parameter.

Similarly, the getRootDir() method and the kernel.root_dir parameter have been deprecated too. The alternative is to use the getProjectdir() and kernel.project_dir method introduced in Symfony 3.3:

# 'root_dir' is where the Kernel class is stored (src/ by default) and
# 'project_dir' is the main project directory
            # Before
            $dataDir: '%kernel.root_dir%/../var/data/'
            # After
            $dataDir: '%kernel.project_dir%/var/data/'

Deprecated some console options

We've removed the original content of this blog post section because the related change was reverted before the Symfony 4.2 release. You can keep using both the console options and the environment variables:

# Using options to control the environment and the debug behavior
$ php bin/console command_name --env=test --no-debug

# Using env vars to control the environment and the debug behavior
$ APP_ENV=test APP_DEBUG=0 php bin/console command_name

Deprecated ContainerAwareCommand

Contributed by
Robin Chalas
in #28415.

The ContainerAwareCommand class has been deprecated. It was used in the past to create commands extending from it so they had direct access to the app service container. The alternative is to extend commands from the Command class and use proper service injection in the command constructor, as explained in the main article about the Symfony Console.

TIP: use the make:command utility provided by the MakerBundle to generate commands quickly and following the Symfony recommendations.

Deprecated the base Controller class

Contributed by
Samuel Roze
in #28243.

The base Controller class is the optional class your controllers can extend from to get access to some useful shortcut methods (such us $this->render()). This Controller class has been deprecated in favor of AbstractController.

The new AbstractController base class has the same shortcuts but it's more restrictive about services. You cannot use the $this->get() shortcut to get services. You must follow the modern practices of injecting services in your controller constructor or in the controller action.

TIP: use the make:controller utility provided by the MakerBundle to generate controllers quickly and following the Symfony recommendations.

Deprecated process commands as strings

Contributed by
Nicolas Grekas
in #27821.

Passing commands as strings to the Process class has been deprecated. The alternative is to pass an array of the command parts (name, arguments, options):

use Symfony\Component\Process\Process;

// Before
$process = new Process('ls -l');

// After
$process = new Process(['ls', '-l']);

Deprecated tree builders without root nodes

Contributed by
Christian Flothmann
in #27476.

This deprecation won't affect directly to most developers because it's related to the configuration classes of dependency injection. However, you'll see lots of these deprecation messages because of the bundles used in your application.

Fixing this deprecation will be simple in most cases, so you may contribute a fix to your favorite third-party bundle:

use Symfony\Component\Config\Definition\Builder\TreeBuilder;

// Before
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('acme_root');

// After
$treeBuilder = new TreeBuilder('acme_root');
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.


"The --env and --no-debug console options have been deprecated. "

This makes no sense to me. Now we need 3 commands (in Windows) instead of 1.
Let's move forward!
@Thomas I'm not sure I follow you. Have you seen the "before/after" example? You don't need to actually change your commands, only the way you execute them.
I'm very sad for the ``. It was really helpful to prefix all logs with the `` parameter. Was useful when all logs were centralized. I guess it is easy to find a workaround by just creating a parameter myself. But still...
The "The --env and --no-debug console options have been deprecated." also doesn't quite make sense to me. No other command I have ever run has ever needed me to overwrite environment variables, this seems like an unnecessary interaction with the terminal/shell. Also, does this have the same syntax for all shells, all crons, and really work everywhere in exactly the same way?

I get the environment variables for web requests, as with PHP-FPM / FastCGI you can easily set additional variables and there is no "isolated" command / cron job there, and no command line options. But with console commands, and shell commands in general, I don't think setting environment variables for overriding options is a use case anybody else is following, so this does not seem like best practices to me.
Andreas Leathley: why do you need to override the environment variables at all? Generally you would have one environment and one debug setting per server. A production server might run multiple websites if it's a shared host but it will almost always be an environment called "prod." Even if you also run staging environments on the same server there is nothing wrong with putting environment variables in a .env file for that deployment to override those settings. You could even consider using DotEnv in production even though the documentation advises against it: it's a tiny performance hit, one that is probably negligible for most applications. And finally there is always the option to dockerize your entire environment so you can compartmentalize your environment variables per deployment and per application.

Doing it any of these ways means that you don't have to include debug or env overrides in your commands at all.

I personally don't see an issue with keeping the --env and --no-debug switches as options for those people who have a use case for them but I don't think I'd be affected at all if they're eventually removed.
"The --env and --no-debug console options have been deprecated", same "rant" here. I'm afraid this will make the maintenance of some scripts more painful because passing env variables is not consistent on every operating system or even shells.

I don't see the gains of removing this feature in sf5: maybe someone can explain the intention behind it?
About the --env and --no-debug options, I think this *may* not be quite as big of a deal as we're thinking. My first impression when I saw this PR was also "What? That's useful!".

But, most of the time, I only use the options when I'm running a command on production and I want --env=prod. But, on production, I will already have all of my configuration (including APP_ENV) stored as environment variables (either as real environment variables or the .env file). So, when I run "php bin/console", it will just use the proper environment that the rest of my app is using.

So, maybe it's not really a big deal? I think the focus should not be on the fact that you will need to set the env vars before calling the command. But rather, that your env vars will already be properly set, so you can just run the command with no variables.

Thank you all for your comments. About the controversial deprecation of "--env" and "--no-debug", I've just reworded the original explanation.

As Ryan said, this is not a big deal in practice. You either have the ".env" file properly configured (both in local and remote machines) or you have the "APP_ENV" environment variable already defined in your remote machines.

You only need to deal with these env vars when you want to override the values set in ".env" or the "APP_ENV" vars, which is a very rare use case.
@Jeroen van den Broek: There are many use cases for multiple environments in one application. For example I have two websites in one application, because they share almost all of the data, but on different domains and with a different layout. That would be one. Another one could be that there is an admin environment (completely different admin website on and a user environment (for customers, on The advantage of the environments is that you can separate parts, so that you don't have to include routes, bundles, services or other things you do not want to use or expose in an environment, both for performance or security reasons (or even separation of concerns). At the same time you can still reuse services and logic a lot instead of having to completely switch code bases all the time. Some might just use "dev" or "prod", but in one application I am using 13 environments with different security settings and domains, and that works very well.

If you want to do things like cache:clear, cache:warmup or similar additional things in your application, it makes sense to always specify an environment, just to make sure you are not using an unknown default one. Because if by some chance somebody changes the environment variable suddenly all scripts could work differently.
@Javier Eguiluz: Having multiple environments seems like a likely use case for me, not a rare one, if you have just an application of some complexity. Maybe I am wrong, but is there any data on how people are using environments, or how many they are using? Because I would not assume by default that all people are only using "dev", "test" and "prod" environments - it might easily be very different for many projects.

Maybe this would also be something to ask the Symfony users in some kind of survey. I have noticed that Symfony has strongly been transformed to be simpler in its recommendations, like not using bundles, or in this case not using many environments and basically just having "one" production environment for an application. But this might not reflect how people are using Symfony.
I use environments in a CLI application that I run on a jump server. Basically `bin/console --env=prod app:cache:clear` to clear the cache on all of the production app servers. It's a Symfony app that exposes certain tasks to admin users and developers without them having to know anything about the underlying infrastructure.

Though, now that I think about it. I guess I shouldn't have been using the `--env` option. I'll have to implement a custom option/argument.
Personally I think the push toward using environmental variables has been a bad decision. So far I have not felt any benefit from it, and it has been a huge headache for my project.

For example, when using Symfony with nginx if an application parameter contains a dollar sign then you are in trouble. Nginx provides no method of escaping a dollar sign in a fastcgi_param directive. You could just use dotenv in production, but that comes with a performance hit. And due to the nature of this issue you very likely won’t find out about that until you deploy your application to prod.

Environmental variables are handled differently in different shells and servers. Moving to them means going from a custom system that works the same everywhere to one that works differently depending on where it is. And the documentation doesn’t really mention of any of this - which makes sense. Environmental variables come with too many circumstantial escaping/quoting edge cases to try to document, and mostly they aren’t Symfony specific issues. But they are still things you might run into while using Symfony. It’s a nice little minefield for users to run into at some point.

deprecating the --env and the --no-debug is really a bad decision, it makes the use on windows much more complicated. this is really a very bad DX.

php bin/console --env=dev
Symfony 3.4.12 (kernel: src, env: dev, debug: true)
(fully working symfony console with no errors)


APP_ENV=dev php bin\console
'APP_ENV' is not recognized as an internal or external command,
operable program or batch file.


λ cmd /V /C "set APP_ENV=dev&& php bin\console"
[WARNING] Some commands could not be registered:
In EnvVarProcessor.php line 76:
Environment variable not found: "DATABASE_URL_LEGACY".
Symfony 3.4.12 (kernel: src, env: dev, debug: true)
In EnvVarProcessor.php line 76:
Environment variable not found: "APP_SECRET".

also the handy autocomplete possibility with clink on windows and bash-completion on linux is gone with this change. environment variables are cool but not the holy grail for everything. there is a reason for having flags on commands. imagine you have to call all commands like this:

URL= RECURSIVE=true OUTPUT_FILE=foo.html wget

please revert this.
\end of github PR comment

this is too much pain for no real gain. i often compare software to houses, for a house you have to decide if you want a flat roof OR a pitched roof but for software you can have both. why removing a handy feature?
Symfony is getting too much Docker oriented with env vars. This make server hosting several applications harder to configure.

And I'm worried about launch backgroud process now since the string constructor is deprecated. How are we suppose to launch such command now:

> new Process('nohup very-long-command &');
openend an issue about the console deprecations:
@Vinorcola I don't think Docker is responsible for the evolution of Symfony when it comes to configuration, this aspect was always linked to the 12-factor principle, IMO, Symfony is just in the period where the alignment with other solution is a good idea and can improve the developer life.

If you look at a modern hosting solution, the env approach is way easier and natural, when it comes to an older solution, the vhost env variables approach can be a solution (not for every project for sure).

If you really look at the configuration aspect, only Symfony > 3.4 support env variables so that's not linked to 99% of actual applications (which run mostly in < 3.4)
How would I use prepared commands ( when passing an array to the Process component? Or is this obsolete now?
@Andreas: "There are many use cases for multiple environments in one application"

Then use different entry points. Create an environment-specific console and index.php files. It's really not that big of a deal.
@Vinorcola: You can be explicit about using strings.

>new Process(['sh', '-c', 'nohup very-long-command &'])
Does the template directory deprecation also apply to the PHP templating engine? Or is just for Twig?
If using the PHP templating engine the templates still have to be stored in src/Resources/views/ or they cannot be found.

Comments are closed.

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