20 August, 2019
Updates… As we all know, they are annoying yet necessary. At some point, technologies you’ve used are going to be discontinued, outdated or unsafe. And long-term projects have to keep up with the ever-changing environment. Today we’re gonna tell you about updating Symfony 2.8 framework to 3.4 – a new version with the longest period of support available. At The Software House, we’ve experienced this process in two big projects. And this is their story.
Few words about Symfony and its versions
Symfony is a PHP web application framework and a set of reusable PHP components/libraries. It’s been around since 2005 and it’s fairly popular among PHP developers. No wonder – this framework aims at replacing repetitive coding tasks and speeding up the maintenance processes. We’re not gonna get into details – if you’re here, you surely know a thing or two about this framework. Since updating Symfony version is the core of this article, what we need to focus on is a roadmap. So, in the picture below, you can actually see the latest evolution of Symfony.
As you can see, if your project uses Symfony 2.8, it hasn’t supported bug fixes since November 2018 and will no longer support security fixes by November 2019 – which is going to happen very soon. That means Symfony 2.8 will be discontinued and no longer receive any new features. So, if you want your application nicely up-and-running, you’ll need a major upgrade to Symfony 3.4. Also, if you’re in the middle of creating a project – including the latest 3.4 version is a no-brainer.
We’re going to focus on updating to Symfony 3.4. It got the longest period of support, but at the same time, it wasn’t a revolution.
The development team and contributors behind Symfony have listened to the feedback and they have adapted to users’ opinions. However, the 3.4 also came with a whole new directory structure and different location for crucial key files and components.
Again, we’re not going to get into the details here. If you’re interested in the list of the new features, you will find a list of the most important changes and the entire catalogue of 200+ new small and big features in Symfony 3.4 on Symfony’s official website. Now, let’s focus on…
What problems does Symfony upgrade solve?
At The Software House, we’ve used the Symfony framework in plenty of our projects – just take a look at our portfolio. Here, we’re going to focus on two applications that we’ve successfully updated. One is a core system for the leading Finnish employee benefits provider, and the other is a Swiss ticket-management platform for event management.
The need for updating both platforms resulted from the fact that they were mature projects, developed throughout many years. Therefore, the tools previously used by us slowly ceased to be supported and the technological debt was growing. Over time, most of the modules became outdated which caused security threats and slowed down our work. Unacceptable, right?
Our priority has always been and ever will be to offer our end-users the safest and the most efficient application possible. That’s why we decided to upgrade the Symfony version, which also meant updating PHP as well.
Using newer solutions saves time, makes the code far more transparent and allows new programmers to join the project much faster. Explaining the intricate elements of the system is also much easier when using up-to-date solutions – the complexity of the code is reduced and day-to-day maintenance becomes a piece of cake. So, where do we begin?
Our timeline of Symfony update
The timeline begins in 2017 when the 2.8 version was still being supported. Around that time we learned about the upcoming Symfony 3.4 – most importantly that it will receive a long period of support. Based on that knowledge, we decided to wait for this version to appear, and instead of introducing little fixes with every new update, to rewrite our projects to 3.4 straight away.
We knew that the 2.8 version will lose the possibility of bug and security fixes in 2018 and 2019 respectively – that’s why we needed to fully implement 3.4 in both projects before that happened. So, when Symfony 3.4 was released in late 2017, we were already prepared for the upcoming changes and we got down to business immediately. Eventually, everything was written, tested and implemented at the beginning of 2019. Now, both projects are absolutely future-proof – at least until the end of 2021 when Symfony 3.4 maintenance period will be over and will no longer support security errors fixes.
Now you probably want to know what exactly was done to upgrade the projects to Symfony 3.4?
The Symfony 3.4 implementation process in our projects
The main challenge for our developers was to update the obsolete code and minor fixes on features. We’ve upgraded the Symfony version and all the packages (vendors) we use.
When updating our projects from Symfony 2.8 to Symfony 3.4, it was absolutely necessary to upgrade PHP to a version higher than 7.0 as well – due to the dependencies.
Normally, no change would be required, but dependencies in those particular projects forced us to do so. However, the PHP upgrade is still profitable – among other facilities, it visibly improves performance.
Bundles and testing
Symfony uses so-called bundles – they are similar to plug-ins in other programs. The main difference is that Symfony is built with packages, including the framework’s core and the application’s code. They provide flexibility in pre-building functionalities based on third-party packages or in the distribution of own packages. And, unfortunately, some of them ceased to be supported. To upgrade the Symfony version, we had to adapt the older packages ourselves and make them compatible with the newer version. It required creating forks – copies of repositories that are especially popular for open-source projects. Thanks to this, we were able to copy the entire project, develop it independently to suit our needs and manually fix problems for higher versions of PHP and Symfony.
We started with launching integration/functional tests and checking what kinds of errors occurred. Having gathered all pieces of information about the errors, we introduced corrections in the code and then ran the tests again. This is quite a tedious process, repeated until all problems are solved. The next step was manual testing. We collected feedback and, after a few new errors appeared, we had to fix them by making changes to the code and started the automated and server tests from scratch again.
All this was really difficult – by updating some elements you caused other components to fail. Both platforms are very complex and there are a lot of dependencies in them. Changes in one place may have a negative effect on subsequent elements. After upgrading PHP, we were able to use the higher version of Symfony but on the other hand, a lot of things stopped working (which was super exhausting).
One thing that we had to do right after the update, was to get rid of all the deprecations that prevent Symfony from working.
Some components were so old that they weren’t in there anymore. Therefore, we had to adapt part of the code to the new structure and methods.
We had no other choice but adopt the step-by-step technique – we introduced new solutions, tested them, checked if Symfony functions work as they should after subsequent changes… In fact, it was only when we solved all the possible conflicts between the components that we could go back to testing the applications themselves.
Then we stumbled upon an unpleasant surprise – it turned out that due to the changes in versioning of our tools and PHP update, part of our tests stopped working. Would you believe it?
The battle of components
We have a really good example that illustrates the conflict between components. You want to update the X package to a certain version, but it turns out that the Y package you use is in a different version that prevents both of them from functioning. Information on any non-compliance issues can be found on the packagist page. In the “requires” and “conflicts” sections, you can find a lot of help when it comes to updating subsequent packages.
In short – if you want to update the X package required for the operation of the Y package and the X package does not meet the requirements, you’re unable to touch either X or Y.
In addition, we had to rewrite certain elements for those that use newer vendors/bundles and ensure the same operation as before the upgrade. It all must have happened in a transparent way with platforms continuing to work correctly. That’s why we decided it was a high time to use Docker.
Docker enters the game
In our development environment, most things were done manually or through developer images. We wanted to have a more flexible solution. That’s why we introduced Docker to containerize all components: database, queuing system and PHP. The initial assumption was to upgrade PHP from 7.0 to 7.1. Therefore, we had to check our platforms with 7.0, 7.1 and finally 7.2 versions. Thanks to Docker – which allows building the environment from containers resembling elements of the puzzle – we managed to carry out these tests much more efficiently. We were able to switch between PHP versions and test the functioning of applications in various environments.
How did it work? We had a file defining our test environment (along with specific containers, e.g. for PHP) and before we started testing, the example entry looked like this:
And when we wanted to change the version, it was enough to switch the number in the following way:
The final outcome
Upgrading Symfony 2.8 to 3.4 version is not rocket science. If done with the right tools, there’s no chance that the upgrade will break the code and ruin the product. Having that in mind, during the process of updating both aforementioned applications – and the technology behind them, Symfony – Docker has made it much easier for us to test different versions of PHP. Furthermore, we were able to match the appropriate version of PHP where the highest possible version of Symfony works properly and, at the same time, is compatible with other platforms’ components. Thanks to this, the application has been modernized, code and maintenance – simplified, and security and performance – increased.