Upgrading a Major Version (e.g. 2.7.0 to 3.0.0)

Every two years, Symfony releases a new major version release (the first number
changes). These releases are the trickiest to upgrade, as they are allowed to
break backwards compatibility. However, Symfony makes this upgrade process as
smooth as possible.

This means that you can update most of your code before the major release is
actually released. This is called making your code future compatible.

During the lifecycle of a major release, new features are added and method
signatures and public API usages are changed. However,
minor versions should not contain any
backwards incompatible changes. To accomplish this, the "old" (e.g. functions,
classes, etc) code still works, but is marked as deprecated, indicating that
it will be removed/changed in the future and that you should stop using it.

When the major version is released (e.g. 3.0.0), all deprecated features and
functionality are removed. So, as long as you've updated your code to stop
using these deprecated features in the last version before the major (e.g.
2.8.*), you should be able to upgrade without a problem.

To help you with this, deprecation notices are triggered whenever you end up
using a deprecated feature. When visiting your application in the
dev environment
in your browser, these notices are shown in the web dev toolbar:

Of course ultimately, you want to stop using the deprecated functionality.
Sometimes, this is easy: the warning might tell you exactly what to change.

But other times, the warning might be unclear: a setting somewhere might
cause a class deeper to trigger the warning. In this case, Symfony does its
best to give a clear message, but you may need to research that warning further.

And sometimes, the warning may come from a third-party library or bundle
that you're using. If that's true, there's a good chance that those deprecations
have already been updated. In that case, upgrade the library to fix them.

Once all the deprecation warnings are gone, you can upgrade with a lot
more confidence.

When you run your tests using PHPUnit, no deprecation notices are shown.
To help you here, Symfony provides a PHPUnit bridge. This bridge will show
you a nice summary of all deprecation notices at the end of the test report.

All you need to do is install the PHPUnit bridge:

1

$ composer require --dev symfony/phpunit-bridge

Now, you can start fixing the notices:

1
2
3
4
5
6
7
8
9
10
11
12
13

$ phpunit
...
OK (10 tests, 20 assertions)
Remaining deprecation notices (6)
The "request" service is deprecated and will be removed in 3.0. Add a typehint for
Symfony\Component\HttpFoundation\Request to your controller parameters to retrieve the
request instead: 6x
3x in PageAdminTest::testPageShow from Symfony\Cmf\SimpleCmsBundle\Tests\WebTest\Admin
2x in PageAdminTest::testPageList from Symfony\Cmf\SimpleCmsBundle\Tests\WebTest\Admin
1x in PageAdminTest::testPageEdit from Symfony\Cmf\SimpleCmsBundle\Tests\WebTest\Admin

Once you fixed them all, the command ends with 0 (success) and you're
done!

Using the Weak Deprecations Mode

Sometimes, you can't fix all deprecations (e.g. something was deprecated
in 2.8 and you still need to support 2.7). In these cases, you can still
use the bridge to fix as many deprecations as possible and then switch
to the weak test mode to make your tests pass again. You can do this by
using the SYMFONY_DEPRECATIONS_HELPER env variable:

(you can also execute the command like SYMFONY_DEPRECATIONS_HELPER=weak phpunit).

Tip

Some members of the Symfony Community have developed a tool called
Symfony-Upgrade-Fixer which automatically fixes some of the most common
deprecations found when upgrading from Symfony 2 to Symfony 3.

If you get a dependency error, it may simply mean that you need to upgrade
other Symfony dependencies too. In that case, try the following command:

1

$ composer update symfony/symfony --with-dependencies

This updates symfony/symfony and all packages that it depends on, which will
include several other packages. By using tight version constraints in
composer.json, you can control what versions each library upgrades to.

If this still doesn't work, your composer.json file may specify a version
for a library that is not compatible with the newer Symfony version. In that
case, updating that library to a newer version in composer.json may solve
the issue.

Or, you may have deeper issues where different libraries depend on conflicting
versions of other libraries. Check your error message to debug.

You may also want to upgrade the rest of your libraries. If you've done a
good job with your version constraints in composer.json, you can do
this safely by running:

1

$ composer update

Caution

Beware, if you have some unspecific version constraints in your
composer.json (e.g. dev-master), this could upgrade some
non-Symfony libraries to new versions that contain backwards-compatibility
breaking changes.

There is a good chance that you're done now! However, the next major version
may also contain new BC breaks as a BC layer is not always a possibility.
Make sure you read the UPGRADE-X.0.md (where X is the new major version)
included in the Symfony repository for any BC break that you need to be aware
of.