Fixing Generic Symfony Deprecations


In the previous tutorial we covered the changes needed to take our application from Symfony 3.2 to Symfony 3.4.

Whilst this is only a minor bump, upgrading an existing project to Symfony 3.4 is an important step as it gives the highest chance of identifying, and eliminating any code issues before upgrading.

Identifying Deprecations

Before we make the switch to Symfony 4, it's essential we find and fix and deprecated code.

What this means - in plain English - is that Symfony will tell us about the things in our code that it knows will break in Symfony 4.

We can see these, immediately, by starting the web server we setup in the previous tutorial:

php bin/console server:start

And then, if we browse to our site:

http://127.0.0.1:8000

And without doing anything else, open up the log file:

var/logs/dev.log

You'll see a bunch of entries like this:

[2017-12-09 10:57:02] php.INFO: User Deprecated: Symfony\Component\HttpKernel\Kernel::loadClassCache() is deprecated since version 3.3, to be removed in 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Symfony\\Component\\HttpKernel\\Kernel::loadClassCache() is deprecated since version 3.3, to be removed in 4.0. at /home/chris/Development/crv-symfony-4-updates/githut/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php:401)"} []
[2017-12-09 10:57:02] php.INFO: User Deprecated: Symfony\Component\HttpKernel\Kernel::doLoadClassCache() is deprecated since version 3.3, to be removed in 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Symfony\\Component\\HttpKernel\\Kernel::doLoadClassCache() is deprecated since version 3.3, to be removed in 4.0. at /home/chris/Development/crv-symfony-4-updates/githut/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php:467)"} []
[2017-12-09 10:57:02] request.INFO: Matched route "githut". {"route":"githut","route_parameters":{"username":"codereviewvideos","_controller":"AppBundle\\Controller\\GitHutController::githutAction","_route":"githut"},"request_uri":"http://127.0.0.1:8001/app_dev.php/","method":"GET"} []
[2017-12-09 10:57:02] security.INFO: Populated the TokenStorage with an anonymous Token. [] []
[2017-12-09 10:57:02] php.INFO: User Deprecated: The "github_api" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: The \"github_api\" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. at /home/chris/Development/crv-symfony-4-updates/githut/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Container.php:275)"} []
[2017-12-09 10:57:03] php.INFO: User Deprecated: The "github_api" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: The \"github_api\" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. at /home/chris/Development/crv-symfony-4-updates/githut/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Container.php:275)"} []
[2017-12-09 10:57:04] php.INFO: User Deprecated: Implementing "Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface" without the "reset()" method is deprecated since version 3.4 and will be unsupported in 4.0 for class "EightPoints\Bundle\GuzzleBundle\DataCollector\HttpDataCollector". {"exception":"[object] (ErrorException(code: 0): User Deprecated: Implementing \"Symfony\\Component\\HttpKernel\\DataCollector\\DataCollectorInterface\" without the \"reset()\" method is deprecated since version 3.4 and will be unsupported in 4.0 for class \"EightPoints\\Bundle\\GuzzleBundle\\DataCollector\\HttpDataCollector\". at /home/chris/Development/crv-symfony-4-updates/githut/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Profiler/Profiler.php:215)"} []
[2017-12-09 10:57:04] php.INFO: User Deprecated: The "github_api" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: The \"github_api\" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. at /home/chris/Development/crv-symfony-4-updates/githut/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Container.php:275)"} []
[2017-12-09 10:57:04] php.INFO: User Deprecated: Symfony\Component\HttpKernel\Kernel::loadClassCache() is deprecated since version 3.3, to be removed in 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Symfony\\Component\\HttpKernel\\Kernel::loadClassCache() is deprecated since version 3.3, to be removed in 4.0. at /home/chris/Development/crv-symfony-4-updates/githut/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php:401)"} []
[2017-12-09 10:57:04] php.INFO: User Deprecated: Symfony\Component\HttpKernel\Kernel::doLoadClassCache() is deprecated since version 3.3, to be removed in 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Symfony\\Component\\HttpKernel\\Kernel::doLoadClassCache() is deprecated since version 3.3, to be removed in 4.0. at /home/chris/Development/crv-symfony-4-updates/githut/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php:467)"} []
[2017-12-09 10:57:04] request.INFO: Matched route "_wdt". {"route":"_wdt","route_parameters":{"_controller":"web_profiler.controller.profiler:toolbarAction","token":"273056","_route":"_wdt"},"request_uri":"http://127.0.0.1:8001/app_dev.php/_wdt/273056","method":"GET"} []
[2017-12-09 10:57:04] php.INFO: User Deprecated: Implementing "Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface" without the "reset()" method is deprecated since version 3.4 and will be unsupported in 4.0 for class "EightPoints\Bundle\GuzzleBundle\DataCollector\HttpDataCollector". {"exception":"[object] (ErrorException(code: 0): User Deprecated: Implementing \"Symfony\\Component\\HttpKernel\\DataCollector\\DataCollectorInterface\" without the \"reset()\" method is deprecated since version 3.4 and will be unsupported in 4.0 for class \"EightPoints\\Bundle\\GuzzleBundle\\DataCollector\\HttpDataCollector\". at /home/chris/Development/crv-symfony-4-updates/githut/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Profiler/Profiler.php:215)"} []

Now this is great, in so much as this is a very helpful chunk of output that we can sift through and dissect to find exactly what we need to do to make our app Symfony 4 compatible.

However, personally I find reading log files incredibly taxing on the eyes. Typically I end up copy / pasting chunks out of the logs into a different editor - Sublime Text for example - then bumping the font size up and segmenting each line out with a few keyboard returns. It's a tedious process.

Thankfully, Symfony has us covered here.

As long as you're browsing your site using app_dev.php, you should have access to the Web Debug Toolbar:

symfony's web debug toolbar

As you can see in the screenshot, there's a 'Log' section, which shows 14 deprecations.

You can click on this, and you'll be taken to the Log page, where after clicking the Deprecations tab, you will see the very same output we saw in the raw dev.log file, but presented in a much nicer fashion:

symfony's deprecation log output

Fortunately the GitHut website is only very small. As such we both have comparatively few deprecations, and a very small number of pages to check. On larger sites, this is unfortunately a much larger task.

Fixing Deprecations

Depending on your Symfony experience - and I'm assuming you have very little if you're taking this tutorial - then some or all of the deprecation messages may appear confusing, and scary.

Google is your friend.

My advice is to copy the full message out, and paste directly into Google.

If it's a common warning then the first page should contain plenty of results describing what the issue is, why it's an issue, and how to fix said issue.

The first two problems fall into this category:

  • User Deprecated: Symfony\Component\HttpKernel\Kernel::loadClassCache() is deprecated since version 3.3, to be removed in 4.0.
  • User Deprecated: Symfony\Component\HttpKernel\Kernel::doLoadClassCache() is deprecated since version 3.3, to be removed in 4.0.

These are issues with code that Symfony provides for us.

We can fix them easily enough by removing the line:

// web/app_dev.php

$kernel->loadClassCache(); // remove this line

And also removing the line:

// web/app.php

$kernel->loadClassCache(); // remove this line

Once done, refresh your page and notice the counter has dropped from 14 to 12. We're off and running.

Now, the truth is, this change is somewhat unnecessary. When we come to install Symfony 4 we will no longer use web/app.php and web/app_dev.php. We will instead use the entirely new public/index.php. But all the same, we're making this change.

More Generic Symfony Deprecations

We're going to skip the deprecations in our own framework integration code, for the moment, and continue fixing the generic stuff that will very likely appear in any Symfony project working towards a Symfony 3.4 / Symfony 4 migration.

This means we're skipping:

User Deprecated: The "github_api" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.

And we're also skipping:

User Deprecated: Implementing "Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface" without the "reset()" method is deprecated since version 3.4 and will be unsupported in 4.0 for class "EightPoints\Bundle\GuzzleBundle\DataCollector\HttpDataCollector".

Because this is related to a bundle we're using, and that is another topic we will cover, but separately.

We're moving on to:

Using the unquoted scalar value "!event" is deprecated since version 3.3 and will be considered as a tagged value in 4.0. You must quote it in "/home/chris/Development/crv-symfony-4-updates/githut/app/config/config_dev.yml" on line 20.

Sounds scary, but is super easy to fix:

// app/config/config_dev.yml

monolog:
    handlers:
        main:
            type: stream
            path: "%kernel.logs_dir%/%kernel.environment%.log"
            level: debug
            channels: [!event]
        console:
            type:   console
            channels: [!event, !doctrine]

All this is saying is that !event needs to become "!event".

// app/config/config_dev.yml

monolog:
    handlers:
        main:
            type: stream
            path: "%kernel.logs_dir%/%kernel.environment%.log"
            level: debug
            channels: ["!event"]
        console:
            type:   console
            channels: ["!event", "!doctrine"]

And because:

Using the unquoted scalar value "!doctrine" is deprecated since version 3.3 and will be considered as a tagged value in 4.0. You must quote it in "/home/chris/Development/crv-symfony-4-updates/githut/app/config/config_dev.yml" on line 23.

We're also updating !doctrine, too.

That takes us down from 12 to 9 deprecations.

The "framework.trusted_proxies" configuration key has been deprecated in Symfony 3.3. Use the Request::setTrustedProxies() method in your front controller instead.

There's a blog post covering this exact message in depth.

Basically if you don't have any trusted_proxies set, which we don't, then all you need to do is remove the line from config.yml:

# app/config/config.yml

framework:
    # ... other stuff
-    trusted_proxies: ~

Trusted proxies is a setting used in larger environments. You can read more here.

Not setting "logout_on_user_change" to true on firewall "main" is deprecated as of 3.4, it will always be true in 4.0.

This is undocumented, at the time of writing, but the gist of my change is:

# app/config/security.yml

security:
    firewalls:
        main:
+           logout_on_user_change: true
            anonymous: ~

Down to 7 outstanding deprecations now.

Final Generic Symfony Deprecation Fixes

We have 7 outstanding deprecations at this point, but 3 of these are generic to Symfony, rather than specific to us:

Autowiring-types are deprecated since Symfony 3.3 and will be removed in 4.0. Use aliases instead for "Psr\Log\LoggerInterface".

And:

Symfony\Component\HttpKernel\DependencyInjection\Extension::addClassesToCompile() is deprecated since version 3.3, to be removed in 4.0.

Though not immediately obvious, the fix here is to ensure all our dependencies are as up to date as possible, for Symfony 3.4.

To achieve this, I have no scientific method.

I simply copy whatever the Symfony Standard Edition uses:

This means the resulting require block in composer.json looks like this:

    "require": {
        "php": ">=5.5.9",
        "doctrine/doctrine-bundle": "^1.6",
        "doctrine/doctrine-cache-bundle": "^1.2",
        "doctrine/orm": "^2.5",
        "incenteev/composer-parameter-handler": "^2.0",
        "sensio/distribution-bundle": "^5.0.19",
        "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": "3.4.*",
        "twig/twig": "^1.0||^2.0",

        "guzzlehttp/guzzle": "^6.1",
        "eightpoints/guzzle-bundle": "^4.5",
        "symfony/web-server-bundle": "^3.4"
    },

Changing dependencies means we need to run composer update:

$ composer update

Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 0 installs, 2 updates, 0 removals
  - Updating symfony/monolog-bundle (v3.1.2 => v2.12.1) Loading from cache
  - Updating sensio/framework-extra-bundle (v5.1.3 => v3.0.28) Loading from cache

This leaves us with two (but reported as 4) remaining problems to solve.

Code For This Video

Get the code for this video.

Episodes

# Title Duration
1 What happened to my Web Server? 04:09
2 Fixing Generic Symfony Deprecations 07:11
3 Fixing Deprecations In Our Own Code 08:52
4 Fixing Third Party Bundle Deprecations (Indirectly) 05:38
5 [Part 1/2] Migrating to Symfony 4.0 with Flex 06:44
6 [Part 2/2] Migrating to Symfony 4.0 with Flex 10:44