[Part 1/2] Migrating to Symfony 4.0 with Flex
Our code is now deprecation free. We're good and ready to migrate from Symfony 3.4 to Symfony 4.
There's still more work to be done, however. The fun never stops.
There are two links we need concern ourselves with:
- http://symfony.com/doc/current/setup/upgrade_major.html
- http://symfony.com/doc/current/setup/flex.html#upgrading-existing-applications-to-flex
Let's start by following the major upgrade guidance.
First, we need to bump up to Symfony 4.0:
# composer.json
"require": {
- "symfony/symfony": "3.4.*",
+ "symfony/symfony": "^4.0",
And then if we continue following the guidance:
composer update symfony/symfony
# or
composer update symfony/symfony --with-dependencies
Well, either of these will fail. At least they do for me.
This is a rather frustrating exercise, so I'm going to skip ahead to the Symfony Flex Upgrade Guide and crack on from there.
Migrating To Symfony Flex
The long and short of this process can be boiled down to two steps:
- Create a new Symfony Flex project
- Copy / paste all the interesting bits from the old project to the new
This isn't quite as straightforward as it sounds, of course.
But let's get on with it.
Create a new empty Symfony application
Our current project is kept under git.
For the moment we're going to have to create an entirely new project, and work outside of our git repo until such time as we are happy with our progress. Once we are happy, we will create a new branch and move all the new stuff back into our original project directory.
Messy.
Anyway, here goes:
cd /tmp
composer create-project symfony/skeleton githut-flex
I'm doing this in the /tmp
directory, but you should probably do this in some directory that lasts a little longer.
composer create-project symfony/skeleton githut-flex
Installing symfony/skeleton (v4.0.2)
- Installing symfony/skeleton (v4.0.2) Loading from cache
Created project in githut-flex
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 21 installs, 0 updates, 0 removals
- Installing symfony/flex (v1.0.49) Loading from cache
- Installing symfony/polyfill-mbstring (v1.6.0) Loading from cache
- Installing symfony/console (v4.0.2) Loading from cache
- Installing symfony/routing (v4.0.2) Loading from cache
- Installing symfony/http-foundation (v4.0.2) Loading from cache
- Installing symfony/yaml (v4.0.2) Loading from cache
- Installing symfony/framework-bundle (v4.0.2) Loading from cache
- Installing symfony/http-kernel (v4.0.2) Loading from cache
- Installing symfony/event-dispatcher (v4.0.2) Loading from cache
- Installing psr/log (1.0.2) Loading from cache
- Installing symfony/debug (v4.0.2) Loading from cache
- Installing symfony/finder (v4.0.2) Loading from cache
- Installing symfony/filesystem (v4.0.2) Loading from cache
- Installing psr/container (1.0.0) Loading from cache
- Installing symfony/dependency-injection (v4.0.2) Loading from cache
- Installing symfony/config (v4.0.2) Loading from cache
- Installing psr/simple-cache (1.0.0) Loading from cache
- Installing psr/cache (1.0.1) Loading from cache
- Installing symfony/cache (v4.0.2) Loading from cache
- Installing symfony/dotenv (v4.0.2) Loading from cache
Writing lock file
Generating autoload files
Symfony operations: 4 recipes (fbe08f5a74d28474d7ff1ed5a555dcc9)
- Configuring symfony/flex (>=1.0): From github.com/symfony/recipes:master
- Configuring symfony/framework-bundle (>=3.3): From github.com/symfony/recipes:master
- Configuring symfony/console (>=3.3): From github.com/symfony/recipes:master
- Configuring symfony/routing (>=3.3): From github.com/symfony/recipes:master
Executing script cache:clear [OK]
Executing script assets:install --symlink --relative public [OK]
What's next?
* Run your application:
1. Change to the project directory
2. Execute the php -S 127.0.0.1:8000 -t public command;
3. Browse to the http://localhost:8000/ URL.
Quit the server with CTRL-C.
Run composer require server for a better web server.
* Read the documentation at https://symfony.com/doc
$ cd githut-flex
Ok sweet, we have our new app.
Merge Up composer.json
Here's the official guidance:
Merge the
require
andrequire-dev
dependencies defined in your original project'scomposer.json
file to thecomposer.json
file of the new project (don't copy thesymfony/symfony
dependency, but add the relevant components you are effectively using in your project).
Here's our old deps:
"require": {
"php": "^7.1.2",
"doctrine/doctrine-bundle": "^1.6",
"doctrine/doctrine-cache-bundle": "^1.2",
"doctrine/orm": "^2.5",
"incenteev/composer-parameter-handler": "^2.0",
"sensio/framework-extra-bundle": "^5.0.0",
"symfony/monolog-bundle": "^3.1.0",
"symfony/polyfill-apcu": "^1.0",
"symfony/swiftmailer-bundle": "^2.6.4",
"symfony/symfony": "^4.0",
"twig/twig": "^1.0||^2.0",
"guzzlehttp/guzzle": "^6.1",
"eightpoints/guzzle-bundle": "^7.2.1",
"symfony/web-server-bundle": "^3.4"
},
"require-dev": {
"sensio/generator-bundle": "^3.0",
"symfony/phpunit-bridge": "^3.0"
},
And the new:
"require": {
"php": "^7.1.3",
"ext-iconv": "*",
"symfony/console": "^4.0",
"symfony/flex": "^1.0",
"symfony/framework-bundle": "^4.0",
"symfony/lts": "^4@dev",
"symfony/yaml": "^4.0"
},
"require-dev": {
"symfony/dotenv": "^4.0"
},
A quick visual inspection of the dependency differences between our old project and new reveals we probably want eightpoints/guzzle-bundle
and symfony/web-server-bundle
.
There is a gotcha here, but for the moment I'm glossing over it.
We can add these two dependencies together as one liner:
composer require symfony/web-server-bundle eightpoints/guzzle-bundle
And in doing so we get to a prompt:
composer require symfony/web-server-bundle eightpoints/guzzle-bundle
Using version ^7.2 for eightpoints/guzzle-bundle
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 8 installs, 0 updates, 0 removals
- Installing symfony/expression-language (v4.0.2) Downloading: 100%
- Installing guzzlehttp/promises (v1.3.1) Loading from cache
- Installing psr/http-message (1.0.1) Loading from cache
- Installing guzzlehttp/psr7 (1.4.2) Loading from cache
- Installing guzzlehttp/guzzle (6.3.0) Loading from cache
- Installing eightpoints/guzzle-bundle (v7.2.1) Loading from cache
- Installing symfony/process (v4.0.2) Downloading: 100%
- Installing symfony/web-server-bundle (v4.0.2) Downloading: 100%
Writing lock file
Generating autoload files
Symfony operations: 2 recipes (5a9631b8ff1054ad71cceef8ab1e637a)
- WARNING eightpoints/guzzle-bundle (>=7.0): From github.com/symfony/recipes-contrib:master
The recipe for this package comes from the "contrib" repository, which is open to community contributions.
Do you want to execute this recipe?
[y] Yes
[n] No
[a] Yes for all packages, only for the current installation session
[p] Yes permanently, never ask again for this project
(defaults to n):
I'm going to hit y
here as I know and trust this bundle:
y
- Configuring eightpoints/guzzle-bundle (>=7.0): From github.com/symfony/recipes-contrib:master
- Configuring symfony/web-server-bundle (>=3.3): From github.com/symfony/recipes:master
Executing script cache:clear [OK]
Executing script assets:install --symlink --relative public [OK]
As a side note you can see all the available Flex 'recipes' here. A recipe is a set of instructions that allows a bundle to install and auto-configure itself properly. No more copy / paste to AppKernel.php
, etc.
Install the dependencies in the new project
Again the full guidance:
Install the dependencies in the new project executing composer update. This will make Symfony Flex generate all the configuration files in config/packages/
Simple enough:
composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Generating autoload files
Executing script cache:clear [OK]
Executing script assets:install --symlink --relative public [OK]
Nothing to see here, move along, move along.
Review the generated config/packages/*.yaml
files and make any needed changes
The full guidance:
Review the generated
config/packages/*.yaml
files and make any needed changes according to the configuration defined in theapp/config/config_*.yml
file of your original project. Beware that this is the most time-consuming and error-prone step of the upgrade process.
Ok, so up until this point we were moving along at a brisk clip. Now we need to do some chore work.
First up, what's this config/packages
directory all about?
ls -la config/packages
total 28
drwxrwxr-x 4 chris chris 4096 Dec 16 10:33 .
drwxrwxr-x 3 chris chris 4096 Dec 16 10:27 ..
drwxrwxr-x 2 chris chris 4096 Dec 16 10:27 dev
-rw-rw-r-- 1 chris chris 565 Dec 16 10:33 eight_points_guzzle.yaml
-rw-rw-r-- 1 chris chris 348 Dec 16 10:27 framework.yaml
-rw-rw-r-- 1 chris chris 54 Dec 16 10:27 routing.yaml
drwxrwxr-x 2 chris chris 4096 Dec 16 10:27 test
Unsurprisingly it's the directory that holds all the configuration based on our installed packages.
Well, we have been making use of only one third party bundle. This bundle - eightpoints/guzzle-bundle
- brings in a new bit of autogenerated configuration. This is because eightpoints/guzzle-bundle
has a defined Recipe.
To cut a long story short, we need to migrate our config from our old project to the new eight_points_guzzle.yml
file:
# config/packages/eight_points_guzzle.yaml
eight_points_guzzle:
clients:
8p_guzzle_client:
base_url: ""
In case you're wondering what is in the dev
and test
subdirectories:
ls -la config/packages/dev
total 12
drwxrwxr-x 2 chris chris 4096 Dec 16 10:27 .
drwxrwxr-x 4 chris chris 4096 Dec 16 10:40 ..
-rw-rw-r-- 1 chris chris 57 Dec 16 10:27 routing.yaml
ls -la config/packages/test
total 12
drwxrwxr-x 2 chris chris 4096 Dec 16 10:27 .
drwxrwxr-x 4 chris chris 4096 Dec 16 10:40 ..
-rw-rw-r-- 1 chris chris 138 Dec 16 10:27 framework.yaml
We're done here for GitHut, but on a real project this step takes significantly longer. At least, it has done for me.
Move over parameters.yml
The guidance:
Move the original parameters defined in
app/config/parameters.*.yml
to the newconfig/services.yaml
and.env
files depending on your needs.
Ahh, well we don't have any config in our parameters.yml
file in the GitHut series. Therefore at first glance it appears we have nothing to do here.
But we do.
This step should also incorporate migrating your app/config/services.yml
files (and any other service
files you have) to the new structure. We have two custom entries in app/config/services.yml
:
# app/config/services.yml
services:
# other stuff removed for brevity
AppBundle\Service\HttpClientInterface: '@AppBundle\Service\GuzzleHttpClient'
GuzzleHttp\Client: "@eight_points_guzzle.client.8p_guzzle_client"
These entries need moving to the new project:
# config/services.yaml
services:
# other stuff removed for brevity
AppBundle\Service\HttpClientInterface: '@AppBundle\Service\GuzzleHttpClient'
GuzzleHttp\Client: "@eight_points_guzzle.client.8p_guzzle_client"
There is a problem here that a good IDE like PhpStorm will alert you too.
AppBundle
needs updating to App
. We will get on to that shortly. For now, I'm leaving as is.
Are We There Yet?
There are still three more steps to go before we have successfully migrated our project from Symfony 3 to Symfony 4.
We're going to tackle these remaining steps in the next video.