I’ve upgraded my site from Symfony version 3 to 4, without using Symfony Flex. I didn’t upgrade so much for new features, but mainly to be up to date, especially with Symfony 5 not far off.
Symfony provides some upgrade instructions in a general major version upgrade and a ‘symfony/symfony’ upgrade guide. They push for major changes to directory structure and switching to Flex. They also don’t seem to mention how to deal with certain things from standard edition.
I wanted a minimal upgrade path that didn’t require major changes from what I have. I didn’t really want to switch to Flex. So I upped the Symfony version and then worked my way through the problems I encountered until everything worked. You can see the changes in my commits b970081, and some tweaks in 81ba8bb and 0a2e1cc.
My project isn’t exactly the same as standard edition, but it is similar enough that the required changes should be similar. I will describe them below.
Deprecations
Before upgrading to Symfony 4, you will want to remove all deprecation notices. Symfony has a really nice version system of marking all backward-incompatible changes as deprecated in the final point version before the next major version. It shows notices for these deprecations in the toolbar in Symfony’s dev environment, and in phpunit when using symfony/phpunit-bridge
.
So, as described in Symfony’s guide, you would make sure you are on 3.4, and then visit pages in dev environment and / or run your unit tests. The notices will hopefully give a good clue as to what needs fixed. Fix them all, and you should be ready for the update.
Dependencies
Composer is used to manage dependencies in a Symfony project. Changing the version that it installs is as simple as changing the version constraints of the desired package(s) in composer.json
and then running composer update
. In this case, you would update the constraints for "symfony/symfony"
and "symfony/phpunit-bridge"
to "^4"
.
Conflicts
Of course, if the new version(s) conflict with other dependency constraints, composer will throw an error. Upgrade "symfony/swiftmailer-bundle"
to "^3.1"
if installed. You must remove the dependencies "sensio/distribution-bundle"
and "sensio/generator-bundle"
, because they don’t work with Symfony 4.
With bundles dependencies removed, they must also be remove from the kernel, normally at app/AppKernel.php
. Remove the following lines:
$bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
$bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
These bundles are also used for some scripts run by composer after install / update. Back in composer.json
, replace the following lines:
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget"
with:
"bin/console cache:clear --env prod",
"bin/console cache:clear",
"bin/console assets:install --symlink --relative web"
These do basically the same thing as two of those lines, and the other ones are no longer relevant.
Back in composer.json
, if you have platform config of "php": "5.6"
, remove that. Symfony 4 requires PHP >= 7.1.
Service loading
The latest version of standard edition already explicitly pulls in AppBundle
classes as services (with some autoconfigure
magic), but if your bundles do not, they will need to. Commands, at the least, no longer are loaded automatically. You will want something like this in your app/config/service.yml
:
services:
_defaults:
autoconfigure: true
autowire: true
public: false
AppBundle\:
exclude: '%kernel.project_dir%/src/AppBundle/{Entity,Repository,Resources,Tests}'
resource: '%kernel.project_dir%/src/AppBundle/*'
AppBundle\Controller\:
resource: '%kernel.project_dir%/src/AppBundle/*'
tags: ['controller.service_arguments']
Etc
Router
You probably won’t encounter this, but the upgrade to Symfony 4 brought me a headache with a change to the regex handling in the routing component. I had a poorly formed requirement for the host
of some routes that worked in Symfony 3, but not 4. It took me quite a while to track down what the problem was. I had to change a regex like (^[0-9\.]+$)|(^.*:.*:.*$)
to ^[0-9\.]+|.*:.*:.*$
.
Server
If you use server:run
or server:start
, add "public-dir": "web"
under the extra
key in composer.json
.
Cleanup
In composer.json
, you can remove all of the symfony-
lines in the extra
section, because they were used by removed bundles.
In app.php
and app_dev.php
, you can remove the line that includes bootstrap.php.cache
, because that is no longer generated. You can also remove any lines like:
$kernel->loadClassCache();
$loader = new ApcClassLoader('sf2', $loader);
Finish
You should now be able to run composer update
, and hopefully in a matter of minutes you will have a working Symfony 4 app.
Of course, if you have dependencies or use features beyond what my site or standard edition use, you may encounter other issues. Hopefully, any error messages will lead you in the right direction.