Alexandre Debril

web programmer & open source contributor

A successful upgrade from Symfony 2 to 3

As Feed-io-bundle is now Symfony 3 compliant, the next logical move was to upgrade its demo. The application is just composed of the bundle itself and Bootstrap so the upgrade process should be easy to follow. Let's see what's in the documentation :

There are a couple of steps to upgrading a major version:

   Make your code deprecation free
   Update to the new major version via Composer
   Update your code to work with the new version

Three steps and every thing seems cristal clear, here we go.

Replace deprecated code and configuration

According to the cookbook, you'll have to replace everything that became deprecated during Symfony 2's evolution. To go through the first step, Symfony provides a package called symfony/phpunit-bridge which detects deprecated parts of your code and shows you the way to correct it. Another way to go is to pay attention to deprecations Symfony notices to your application's log, which means to manually test the whole application. Good luck with that. feedio-demo has unit tests (well in fact, one), I'll use the bridge :

phpunit

OK, that's easy. Only one configuration to fix and feedio-demo is ready for the dependencies upgrade.

 Update dependencies with Composer

Seriously, it's a brain killer to understand what's going on in your dependencies and why the f@#& Composer refuses to update it. But let's calm down and take a look at the cookbook. It mentions only one change in composer.json :

- "symfony/symfony": "2.7.*",
+ "symfony/symfony": "3.0.*",

And then run the update command

$ composer update --with-dependencies symfony/symfony

sf3-composer

Yeah right, I love it. I won't list here all the things I tried and the ones that worked, this is not necessary (and boring). Things to do are :

  • sensio/distribution-bundle must be upgraded to version 5.0
  • sensio/generator-bundle and symfony/twig-bundle must be upgraded to version 3.0
  • symfony/assetic-bundle to version 2.7

In my case, Feed-io-bundle's compatibility break is an issue. Version 2. is compatible with Symfony 2. and feedio-bundle 3.0 only compatible with Symfony 3.*, there's no transitional version. The only way to solve this is to remove composer.lock file and vendor/ before running composer install. So be careful with your specific bundles and their dependencies, it can put you in trouble if you don't pay attention to backward compatibility. Here's the commit.

 $ rm -Rf composer.lock vendor/
 $ composer install

Finally, Composer successfully downloaded and installed the project's dependencies. But ...

sf3-ci

Replace the bootstrap

The cache:clear command fails because it it's unable to find Symfony\Component\Console\Input\ArgvInput. Look at the bin/console file in a fresh project built on Symfony 3 :

#!/usr/bin/env php
<?php
// if you don't want to setup permissions the proper way, just uncomment the following PHP line
// read http://symfony.com/doc/current/book/installation.html#configuration-and-setup for more information
//umask(0000);

set_time_limit(0);

require_once __DIR__.'/autoload.php';
require_once __DIR__.'/AppKernel.php';

use Symfony\Bundle\FrameworkBundle\Console\Application;
// etc ...

There's no bootstrap.php.cache anymore. Instead, the code requires autoload.php. But wait, why are we comparing app/console with bin/console ? It's simple : Symfony upgraded its architecture in 3.*, the console script is no longer in app/ but in bin/, which makes more sense. The app/ folder is now dedicated to the application's specific resources like templates and configuration, all binaries are located in the bin folder.

That being said, we'll have to modify our legacy console script to make it compliant with the new Symfony's standards. line 10 :

- require_once __DIR__.'/bootstrap.php.cache';
+ require_once __DIR__.'/autoload.php';

You'll have to do this in every files the bootstrap is required, that means :

  • web/app.php
  • web/app_dev.php
  • phpunit.xml.dist

This time, the application starts. But ...

phpunit-boom

Add symfony/debug to the dependencies

The reason why PHPUnit fails is because the application can't find Symfony\Component\Debug\Debug

debug-crash

The solution is simple

$ composer require symfony/debug

But still ...

ghost-1

Make the little ghost go away

Good news, there's a little ghost that means Symfony works! But not the application, that's still a problem. This time, we can see that the application's maintainer didn't removed a routing configuration included with the default stack. That's easy to fix (and it should have been done a long time ago). But ...

ghost-2

This little ghost likes me, I'm always feeding him with good bugs. And now he's showing me another thing we can't joke with anymore : YAML syntax. I forgot to put a string between quotes in routing.yml which wasn't an issue while the project was built on Symfony 2. Another simple thing to fix ...

debug-bar

It works !

Note that it was simple for me because feedio-demo is a tiny application and all its logic is in a bundle already compliant with Symfony 3.

In a nutshell

Now that we got through the whole process in details, let's sum all this up in the following checklist :

  • install symfony/phpunit-bridge and symfony/debug
  • replace deprecated parts.
  • replace bootstrap.php.cache with autoload.php
  • update with Composer (or reinstall all dependencies if a package doesn't deal with versions transition)
  • clean the annoying leftovers

 Available resources

These are the resources you must use or read during the upgrade of your application :

Final thought

There's one thing to think about before going through the upgrade process. A very simple question: it is worth it ? The answer is not necessarily "yes without any doubt". You must consider this before :

  • 2.8 is the actual LTS and is supported until November 2019
  • some bundles are not yet ready to support Symfony 3
  • such a move on a project means you'll need to test all its features to track regressions. If you have a strong code base with a low code coverage, it's a heavy risk I wouldn't advice you to take.
  • Symfony 3 doesn't introduce key features like version 2 did

On the other hand :

  • A Symfony 3.* version will be the next LTS in the future.
  • Good resources are provided to help you : the bridge, the cookbook and the upgrade guide
  • it can be harmless on projects with a good code coverage

In conclusion, I would consider upgrading mainly if the application is supposed to be online until at least 2020, which is the case for all pure players. And don't forget : the only way to get the health of your live application under control is to upgrade Symfony in a dedicated delivery. That way, you'll be able to rollback without loosing new features if anything goes wrong.