You can upgrade a symfony 2 project to symfony 3 ! But you would need read some advices and important points that you need to know before upgrade.

Important tips that you need to know before upgrade your project from symfony 2 to symfony 3
In this article we will share with you the most significant changes for your code in the new version. We suggest you too a couple of tips before proceed with your upgrade :
  • Check that your server supports at least PHP 5.5.9
  • Make your code deprecation free (using phpunit or pay attention to the symfony dev profiler).
  • Check that all the bundles that you use supports symfony 3 already, otherwise don't upgrade.
  • Time ! As this update can cause problems with your actual code and you may need time to solve them.

Framework

The getRequest method of the base Controller class has been deprecated since Symfony 2.4 and must be therefore removed in 3.0. The only reliable way to get the Request object is to inject it in the action method.

That means that we will not get the request inside the action, instead we'll receive the request as parameter in the function.

namespace myBundle\Controller;

use Symfony\Component\HttpFoundation\Request;

class StartController
{
   public function showAction(Request $request)
   {
       // $request->query->get('aGetParameter')
   }
}

The form.csrf_provider service is removed as it implements an adapter for the new token manager to the deprecated Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface interface. The security.csrf.token_manager should be used instead.

Security

The intention firewall listener setting was renamed to csrf_token_id. 

The csrf_provider firewall listener setting was renamed to csrf_token_generator.

# Using FOSUserBundle for example
main:
    pattern: ^/
    form_login:
        provider: fos_userbundle
        csrf_token_generator: security.csrf.token_manager
        # in Symfony < 2.8, we used instead :
        # csrf_provider: form.csrf_provider

Routing

Some route settings has been renamed and will not work anymore in symfony 3 :

  • The pattern setting has been removed in favor of path
  • The _scheme and _method requirements have been moved to the schemes and methods settings
# Deprecated
article_edit:
   pattern: /article/{id}
   requirements: { '_method': 'POST|PUT', '_scheme': 'https', 'id': '\d+' }

# Now

article_edit:
   path: /article/{id}
   methods: [POST, PUT]
   schemes: https
   requirements: { 'id': '\d+' }

YAML

Although you may think this is not so relevant, if you create your own services, this may be useful.

  • Using a colon in an unquoted mapping value leads to a ParseException.
  • Starting an unquoted string with @, `, |, or > leads to a ParseException. 
  • When surrounding strings with double-quotes, you must now escape \ characters. Not escaping those characters (when surrounded by double-quotes) leads to a ParseException.
# this will lead to a ParseException
class: "Foo\Var"

# escape the characters or simply do not encapsulate a class in quotes
class: "Foo\\Var"
class: Foo\Var

Forms

Type names were removed. Instead of referencing types by name, you must reference them by their fully-qualified class name (FQCN) instead.

We use to give the type as second parameter in the form builder:

$form = $this->createFormBuilder()
->add('name', 'text')
->add('age', 'integer')
->getForm();

however now we can't give the name as a string !

use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\DatetimeType;

// Don't forget to include the typeClass

$form = $this->createFormBuilder()
->add('name', TextType::class) 
->add('age', IntegerType::class)
->add('description', TextareaType::class)
->getForm();

On the types, we found for example : SubmitType, UrlType, FormType, HiddenType, LocaleType etc .. (See Symfony\Component\Form\Extension\Core\Type\ folder for more types)

Passing type instances to Form::add(), FormBuilder::add() and the FormFactory::create*() methods is not supported anymore. Pass the fully-qualified class name of the type instead.

In the controllers we used to create a new instance of the type of your entity :

use thisismyBundle\Form\MyCustomType;

$form = $this->createForm(new MyCustomType(),$entity .......);

Now we'll use instead :

use thisismyBundle\Form\MyCustomType;

$form = $this->createForm(MyCustomType::class,$entity .......);

Passing a Symfony\Component\HttpFoundation\Request instance, as was supported by FormInterface::bind(), is not possible with FormInterface::submit() anymore. You should use FormInterface::handleRequest() instead.

If your Symfony version >= 2.6.* you will not face this issue. The bind method has been removed, you need to use handleRequest instead. Old way :

if ('POST' === $request->getMethod()) {
   $form->bind($request);

   if ($form->isValid()) {
       // do some stuff
   }
}

Now we'll handle the request directly:

$form->handleRequest($request);

if ($form->isValid()) {
   // do some stuff and redirect
}

If you want to know more details or this post doesn't fit with your need, read the complete upgrade list in the symfony repository here. Have fun and may the force be with you on this journey.


Senior Software Engineer at Software Medico. Interested in programming since he was 14 years old, Carlos is a self-taught programmer and founder and author of most of the articles at Our Code World.

Sponsors