This document explains how to upgrade from one Symfony2 PR version to the next one. It only discusses changes that need to be done when using the "public" API of the framework. If you "hack" the core, you should probably follow the timeline closely anyway.
-
Expanded the SerializerInterface, while reducing the number of public methods in the Serializer class itself breaking BC and adding component specific Exception classes.
-
The temporary storage for file uploads has been removed
-
The
Symfony\Component\HttpFoundation\File\File::getExtension()andguessExtension()methods do not return the extension with a.anymore. -
The
emoption of the DoctrineEntityTypeclass now takes the entity manager name instead of the EntityManager instance. If you don't pass this option, the default Entity Manager will be used as before. -
In the Console component:
Command::getFullname()andCommand::getNamespace()have been removed (Command::getName()behavior is now the same as the oldCommand::getFullname()). -
Default Twig form templates have been moved to the Twig bridge. Here is how you can reference them now from a template or in a configuration setting:
Before:
`TwigBundle:Form:div_layout.html.twig`After:
`div_layout.html.twig` -
All settings regarding the cache warmers have been removed.
-
Response::isRedirected()has been merged withResponse::isRedirect()
-
Client::getProfilerhas been removed in favor ofClient::getProfile, which returns an instance ofProfile. -
Some
UniversalClassLoadermethods have been renamed:registerPrefixFallbacktoregisterPrefixFallbacksregisterNamespaceFallbacktoregisterNamespaceFallbacks
-
The event system has been made more flexible. A listener can now be any valid PHP callable.
-
EventDispatcher::addListener($eventName, $listener, $priority = 0):$eventNameis the event name (cannot be an array anymore),$listeneris a PHP callable.
-
The events classes and constants have been renamed:
-
Old class name
Symfony\Component\Form\Eventsand constants:Events::preBind = 'preBind' Events::postBind = 'postBind' Events::preSetData = 'preSetData' Events::postSetData = 'postSetData' Events::onBindClientData = 'onBindClientData' Events::onBindNormData = 'onBindNormData' Events::onSetData = 'onSetData' -
New class name
Symfony\Component\Form\FormEventsand constants:FormEvents::PRE_BIND = 'form.pre_bind' FormEvents::POST_BIND = 'form.post_bind' FormEvents::PRE_SET_DATA = 'form.pre_set_data' FormEvents::POST_SET_DATA = 'form.post_set_data' FormEvents::BIND_CLIENT_DATA = 'form.bind_client_data' FormEvents::BIND_NORM_DATA = 'form.bind_norm_data' FormEvents::SET_DATA = 'form.set_data' -
Old class name
Symfony\Component\HttpKernel\Eventsand constants:Events::onCoreRequest = 'onCoreRequest' Events::onCoreException = 'onCoreException' Events::onCoreView = 'onCoreView' Events::onCoreController = 'onCoreController' Events::onCoreResponse = 'onCoreResponse' -
New class name
Symfony\Component\HttpKernel\CoreEventsand constants:CoreEvents::REQUEST = 'core.request' CoreEvents::EXCEPTION = 'core.exception' CoreEvents::VIEW = 'core.view' CoreEvents::CONTROLLER = 'core.controller' CoreEvents::RESPONSE = 'core.response' -
Old class name
Symfony\Component\Security\Http\Eventsand constants:Events::onSecurityInteractiveLogin = 'onSecurityInteractiveLogin' Events::onSecuritySwitchUser = 'onSecuritySwitchUser' -
New class name
Symfony\Component\Security\Http\SecurityEventsand constants:SecurityEvents::INTERACTIVE_LOGIN = 'security.interactive_login' SecurityEvents::SWITCH_USER = 'security.switch_user'
-
-
addListenerServicenow only takes a single event name as its first argument, -
Tags in configuration must now set the method to call:
-
Before:
<tag name="kernel.listener" event="onCoreRequest" /> -
After:
<tag name="kernel.listener" event="core.request" method="onCoreRequest" />
-
-
Subscribers must now always return a hash:
-
Before:
public static function getSubscribedEvents() { return Events::onBindNormData; } -
After:
public static function getSubscribedEvents() { return array(FormEvents::BIND_NORM_DATA => 'onBindNormData'); }
-
-
-
Form
DateTypeparametersingle-textchanged tosingle_text -
Form field label helpers now accepts setting attributes, i.e.:
{{ form_label(form.name, 'Custom label', { 'attr': {'class': 'name_field'} }) }}- In order to use Swiftmailer, you should now register its "init.php" file via
the autoloader ("app/autoloader.php") and remove the
Swift_prefix from the autoloader. For an example on how this should be done, see the Standard Distribution autoload.php.
-
The settings under
framework.annotationshave changed slightly:Before:
framework: annotations: cache: file file_cache: debug: true dir: /fooAfter:
framework: annotations: cache: file debug: true file_cache_dir: /foo
-
The annotation parsing process has been changed (it now uses Doctrine Common 3.0). All annotations which are used in a class must now be imported (just like you import PHP namespaces with the "use" statement):
Before:
<?php
/**
* @orm:Entity
*/
class AcmeUser
{
/**
* @orm:Id
* @orm:GeneratedValue(strategy = "AUTO")
* @orm:Column(type="integer")
* @var integer
*/
private $id;
/**
* @orm:Column(type="string", nullable=false)
* @assert:NotBlank
* @var string
*/
private $name;
}After:
<?php
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity
*/
class AcmeUser
{
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*
* @var integer
*/
private $id;
/**
* @ORM\Column(type="string", nullable=false)
* @Assert\NotBlank
*
* @var string
*/
private $name;
}- The
Setconstraint has been removed as it is not required anymore.
Before:
<?php
/**
* @orm:Entity
*/
class AcmeEntity
{
/**
* @assert:Set({@assert:Callback(...), @assert:Callback(...)})
*/
private $foo;
}After:
<?php
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints\Callback;
/**
* @ORM\Entity
*/
class AcmeEntity
{
/**
* @Callback(...)
* @Callback(...)
*/
private $foo;
}-
The config under
framework.validation.annotationshas been removed and was replaced with a boolean flagframework.validation.enable_annotationswhich defaults to false. -
Forms must now be explicitly enabled (automatically done in Symfony SE):
framework: form: ~Which is equivalent to:
framework: form: enabled: true -
The Routing Exceptions have been moved:
Before:
Symfony\Component\Routing\Matcher\Exception\Exception Symfony\Component\Routing\Matcher\Exception\NotFoundException Symfony\Component\Routing\Matcher\Exception\MethodNotAllowedExceptionAfter:
Symfony\Component\Routing\Exception\Exception Symfony\Component\Routing\Exception\NotFoundException Symfony\Component\Routing\Exception\MethodNotAllowedException -
The form component's
csrf_page_idoption has been renamed tointention. -
The
error_handlersetting has been removed. TheErrorHandlerclass is now managed directly by Symfony SE inAppKernel. -
The Doctrine metadata files has moved from
Resources/config/doctrine/metadata/orm/toResources/config/doctrine, the extension from.dcm.ymlto.orm.yml, and the file name has been changed to the short class name.Before:
Resources/config/doctrine/metadata/orm/Bundle.Entity.dcm.xml Resources/config/doctrine/metadata/orm/Bundle.Entity.dcm.ymlAfter:
Resources/config/doctrine/Entity.orm.xml Resources/config/doctrine/Entity.orm.yml -
With the introduction of a new Doctrine Registry class, the following parameters have been removed (replaced by methods on the
doctrineservice):doctrine.orm.entity_managersdoctrine.orm.default_entity_managerdoctrine.dbal.default_connection
Before:
$container->getParameter('doctrine.orm.entity_managers') $container->getParameter('doctrine.orm.default_entity_manager') $container->getParameter('doctrine.orm.default_connection')After:
$container->get('doctrine')->getEntityManagerNames() $container->get('doctrine')->getDefaultEntityManagerName() $container->get('doctrine')->getDefaultConnectionName()But you don't really need to use these methods anymore, as to get an entity manager, you can now use the registry directly:
Before:
$em = $this->get('doctrine.orm.entity_manager'); $em = $this->get('doctrine.orm.foobar_entity_manager');After:
$em = $this->get('doctrine')->getEntityManager(); $em = $this->get('doctrine')->getEntityManager('foobar'); -
The
doctrine:generate:entitiesarguments and options changed. Run./app/console doctrine:generate:entities --helpfor more information about the new syntax. -
The
doctrine:generate:repositoriescommand has been removed. The functionality has been moved to thedoctrine:generate:entities. -
Doctrine event subscribers now use a unique "doctrine.event_subscriber" tag. Doctrine event listeners also use a unique "doctrine.event_listener" tag. To specify a connection, use the optional "connection" attribute.
Before:
listener: class: MyEventListener tags: - { name: doctrine.common.event_listener, event: name } - { name: doctrine.dbal.default_event_listener, event: name } subscriber: class: MyEventSubscriber tags: - { name: doctrine.common.event_subscriber } - { name: doctrine.dbal.default_event_subscriber }After:
listener: class: MyEventListener tags: - { name: doctrine.event_listener, event: name } # register for all connections - { name: doctrine.event_listener, event: name, connection: default } # only for the default connection subscriber: class: MyEventSubscriber tags: - { name: doctrine.event_subscriber } # register for all connections - { name: doctrine.event_subscriber, connection: default } # only for the default connection -
Application translations are now stored in the
Resourcesdirectory:Before:
app/translations/catalogue.fr.xmlAfter:
app/Resources/translations/catalogue.fr.xml -
The option
modifiableof thecollectionform type was split into two optionsallow_addandallow_delete.Before:
$builder->add('tags', 'collection', array( 'type' => 'text', 'modifiable' => true, ));After:
$builder->add('tags', 'collection', array( 'type' => 'text', 'allow_add' => true, 'allow_delete' => true, )); -
Request::hasSession()has been renamed toRequest::hasPreviousSession(). The methodhasSession()still exists, but only checks if the request contains a session object, not if the session was started in a previous request. -
Serializer: The NormalizerInterface's
supports()method has been split in two methods:supportsNormalization()andsupportsDenormalization(). -
ParameterBag::getDeep()has been removed, and is replaced with a boolean flag on theParameterBag::get()method. -
Serializer:
AbstractEncoder&AbstractNormalizerwere renamed toSerializerAwareEncoder&SerializerAwareNormalizer. -
Serializer: The
$propertiesargument has been dropped from all interfaces. -
Form: Renamed option value
textofwidgetoption of thedatetype was renamed tosingle-text.textindicates to use separate text boxes now (like for thetimetype). -
Form: Renamed view variable
nametofull_name. The variablenamenow contains the local, short name (equivalent to$form->getName()).
-
The CSRF secret configuration has been moved to a mandatory global
secretsetting (as the secret is now used for everything and not just CSRF):Before:
framework: csrf_protection: secret: S3cr3tAfter:
framework: secret: S3cr3t -
The
File::getWebPath()andFile::rename()methods have been removed, as well as theframework.document_rootconfiguration setting. -
The
File::getDefaultExtension()method has been renamed toFile::guessExtension(). The renamed method now returns null if it cannot guess the extension. -
The
sessionconfiguration has been refactored:-
The
classoption has been removed (use thesession.classparameter instead); -
The PDO session storage configuration has been removed (a cookbook recipe is in the work);
-
The
storage_idoption now takes a service id instead of just part of it.
-
-
The
DoctrineMigrationsBundleandDoctrineFixturesBundlebundles have been moved to their own repositories. -
The form framework has been refactored extensively (more information in the documentation).
-
The
transtag does not accept a message as an argument anymore:{% trans "foo" %} {% trans foo %}Use the long version the tags or the filter instead:
{% trans %}foo{% endtrans %} {{ foo|trans }}This has been done to clarify the usage of the tag and filter and also to make it clearer when the automatic output escaping rules are applied (see the doc for more information).
-
Some methods in the DependencyInjection component's
ContainerBuilderandDefinitionclasses have been renamed to be more specific and consistent:Before:
$container->remove('my_definition'); $definition->setArgument(0, 'foo');After:
$container->removeDefinition('my_definition'); $definition->replaceArgument(0, 'foo'); -
In the rememberme configuration, the
token_provider keynow expects a real service id instead of only a suffix.
-
HttpFoundation\Cookie::getExpire()was renamed togetExpiresTime() -
XML configurations have been normalized. All tags with only one attribute have been converted to tag content:
Before:
<bundle name="MyBundle" /> <app:engine id="twig" /> <twig:extension id="twig.extension.debug" />After:
<bundle>MyBundle</bundle> <app:engine>twig</app:engine> <twig:extension>twig.extension.debug</twig:extension> -
Fixes a critical security issue which allowed all users to switch to arbitrary accounts when the SwitchUserListener was activated. Configurations which do not use the SwitchUserListener are not affected.
-
The Dependency Injection Container now strongly validates the references of all your services at the end of its compilation process. If you have invalid references this will result in a compile-time exception instead of a run-time exception (the previous behavior).
-
Extension configuration classes should now implement the
Symfony\Component\Config\Definition\ConfigurationInterfaceinterface. Note that the BC is kept but implementing this interface in your extensions will allow for further developments. -
The
fingerscrossedMonolog option has been renamed tofingers_crossed.
-
Bundle logical names earned back their
Bundlesuffix:Controllers:
Blog:Post:show->BlogBundle:Post:showTemplates:
Blog:Post:show.html.twig->BlogBundle:Post:show.html.twigResources:
@Blog/Resources/config/blog.xml->@BlogBundle/Resources/config/blog.xmlDoctrine:
$em->find('Blog:Post', $id)->$em->find('BlogBundle:Post', $id) -
ZendBundlehas been replaced byMonologBundle. Have a look at the changes made to Symfony SE to see how to upgrade your projects: https://github.com/symfony/symfony-standard/pull/30/files -
Almost all core bundles parameters have been removed. You should use the settings exposed by the bundle extension configuration instead.
-
Some core bundles service names changed for better consistency.
-
Namespace for validators has changed from
validationtoassert(it was announced for PR9 but it was not the case then):Before:
@validation:NotNullAfter:
@assert:NotNullMoreover, the
Assertprefix used for some constraints has been removed (AssertTruetoTrue). -
ApplicationTester::getDisplay()andCommandTester::getDisplay()method now return the command exit code
-
Symfony\Bundle\FrameworkBundle\Util\Filesystemhas been moved toSymfony\Component\HttpKernel\Util\Filesystem -
The
Executeconstraint has been renamed toCallback -
The HTTP exceptions classes signatures have changed:
Before:
throw new NotFoundHttpException('Not Found', $message, 0, $e);After:
throw new NotFoundHttpException($message, $e); -
The RequestMatcher class does not add
^and$anymore to regexp.You need to update your security configuration accordingly for instance:
Before:
pattern: /_profiler.* pattern: /loginAfter:
pattern: ^/_profiler pattern: ^/login$ -
Global templates under
app/moved to a new location (old directory did not work anyway):Before:
app/views/base.html.twig app/views/AcmeDemoBundle/base.html.twigAfter:
app/Resources/views/base.html.twig app/Resources/AcmeDemo/views/base.html.twig -
Bundle logical names lose their
Bundlesuffix:Controllers:
BlogBundle:Post:show->Blog:Post:showTemplates:
BlogBundle:Post:show.html.twig->Blog:Post:show.html.twigResources:
@BlogBundle/Resources/config/blog.xml->@Blog/Resources/config/blog.xmlDoctrine:
$em->find('BlogBundle:Post', $id)->$em->find('Blog:Post', $id) -
Assetic filters must be now explicitly loaded:
assetic: filters: cssrewrite: ~ yui_css: jar: "/path/to/yuicompressor.jar" my_filter: resource: "%kernel.root_dir%/config/my_filter.xml" foo: bar