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 UPGRADE-4.2.md 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
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
The KernelInterface::getName()
method and the kernel.name
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:
1 2 3 4 5 6 7 8 9
# 'root_dir' is where the Kernel class is stored (src/ by default) and
# 'project_dir' is the main project directory
services:
_defaults:
bind:
# 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:
1 2 3 4 5
# 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
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
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
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):
1 2 3 4 5 6 7
use Symfony\Component\Process\Process;
// Before
$process = new Process('ls -l');
// After
$process = new Process(['ls', '-l']);
Deprecated tree builders without root nodes
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:
1 2 3 4 5 6 7 8 9 10
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
// Before
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('acme_root');
$rootNode->...()->...()->...();
// After
$treeBuilder = new TreeBuilder('acme_root');
$treeBuilder->getRootNode()->...()->...()->...();
"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.
Nice! 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
kernel.name
. It was really helpful to prefix all logs with thekernel.name
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.
Cheers!
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 admin.website.com) and a user environment (for customers, on website.com). 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.
https://github.com/symfony/symfony/pull/28653#issuecomment-432811985
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.
vs
vs
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=http://example.com 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:
openend an issue about the console deprecations: https://github.com/symfony/symfony/issues/28984
@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 (https://symfony.com/blog/new-in-symfony-4-1-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.
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.