UPGRADE FROM 2.x to 3.0 ======================= ### ClassLoader * The `UniversalClassLoader` class has been removed in favor of `ClassLoader`. The only difference is that some method names are different: | Old name | New name | -------- | --- | `registerNamespaces()` | `addPrefixes()` | `registerPrefixes()` | `addPrefixes()` | `registerNamespace()` | `addPrefix()` | `registerPrefix()` | `addPrefix()` | `getNamespaces()` | `getPrefixes()` | `getNamespaceFallbacks()` | `getFallbackDirs()` | `getPrefixFallbacks()` | `getFallbackDirs()` * The `DebugUniversalClassLoader` class has been removed in favor of `DebugClassLoader`. The difference is that the constructor now takes a loader to wrap. ### Config * The `__toString()` method of the `\Symfony\Component\Config\ConfigCache` class was removed in favor of the new `getPath()` method. ### Console * The `dialog` helper has been removed in favor of the `question` helper. * The methods `isQuiet`, `isVerbose`, `isVeryVerbose` and `isDebug` were added to `Symfony\Component\Console\Output\OutputInterface`. * `ProgressHelper` has been removed in favor of `ProgressBar`. Before: ```php $h = new ProgressHelper(); $h->start($output, 10); for ($i = 1; $i < 5; $i++) { usleep(200000); $h->advance(); } $h->finish(); ``` After: ```php $bar = new ProgressBar($output, 10); $bar->start(); for ($i = 1; $i < 5; $i++) { usleep(200000); $bar->advance(); } ``` * `TableHelper` has been removed in favor of `Table`. Before: ```php $table = $app->getHelperSet()->get('table'); $table ->setHeaders(array('ISBN', 'Title', 'Author')) ->setRows(array( array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'), array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'), array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'), )) ; $table->render($output); ``` After: ```php use Symfony\Component\Console\Helper\Table; $table = new Table($output); $table ->setHeaders(array('ISBN', 'Title', 'Author')) ->setRows(array( array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'), array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'), array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'), )) ; $table->render(); ``` ### DependencyInjection * The methods `Definition::setFactoryClass()`, `Definition::setFactoryMethod()`, and `Definition::setFactoryService()` have been removed in favor of `Definition::setFactory()`. Services defined using YAML or XML use the same syntax as configurators. * Synchronized services are deprecated and the following methods have been removed: `ContainerBuilder::synchronize()`, `Definition::isSynchronized()`, and `Definition::setSynchronized()`. ### DoctrineBridge * The `property` option of `DoctrineType` was removed in favor of the `choice_label` option. * The `loader` option of `DoctrineType` was removed. You now have to override the `getLoader()` method in your custom type. * The `Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList` was removed in favor of `Symfony\Bridge\Doctrine\Form\ChoiceList\DoctrineChoiceLoader`. * Passing a query builder closure to `ORMQueryBuilderLoader` is not supported anymore. You should pass resolved query builders only. Consequently, the arguments `$manager` and `$class` of `ORMQueryBuilderLoader` have been removed as well. Note that the `query_builder` option of `DoctrineType` *does* support closures, but the closure is now resolved in the type instead of in the loader. ### EventDispatcher * The interface `Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface` extends `Symfony\Component\EventDispatcher\EventDispatcherInterface`. ### Form * The `max_length` option was removed. Use the `attr` option instead by setting it to an `array` with a `maxlength` key. * The `ChoiceToBooleanArrayTransformer`, `ChoicesToBooleanArrayTransformer`, `FixRadioInputListener`, and `FixCheckboxInputListener` classes were removed. * The `choice_list` option of `ChoiceType` was removed. * The option "precision" was renamed to "scale". Before: ```php $builder->add('length', 'number', array( 'precision' => 3, )); ``` After: ```php $builder->add('length', 'number', array( 'scale' => 3, )); ``` * The method `AbstractType::setDefaultOptions(OptionsResolverInterface $resolver)` and `AbstractTypeExtension::setDefaultOptions(OptionsResolverInterface $resolver)` have been renamed. You should use `AbstractType::configureOptions(OptionsResolver $resolver)` and `AbstractTypeExtension::configureOptions(OptionsResolver $resolver)` instead. * The methods `Form::bind()` and `Form::isBound()` were removed. You should use `Form::submit()` and `Form::isSubmitted()` instead. Before: ```php $form->bind(array(...)); ``` After: ```php $form->submit(array(...)); ``` * 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. Before: ```php if ('POST' === $request->getMethod()) { $form->bind($request); if ($form->isValid()) { // ... } } ``` After: ```php $form->handleRequest($request); if ($form->isValid()) { // ... } ``` If you want to test whether the form was submitted separately, you can use the method `isSubmitted()`: ```php $form->handleRequest($request); if ($form->isSubmitted()) { // ... if ($form->isValid()) { // ... } } ``` * The events `PRE_BIND`, `BIND` and `POST_BIND` were renamed to `PRE_SUBMIT`, `SUBMIT` and `POST_SUBMIT`. Before: ```php $builder->addEventListener(FormEvents::PRE_BIND, function (FormEvent $event) { // ... }); ``` After: ```php $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) { // ... }); ``` * The option "`virtual`" was renamed to "`inherit_data`". Before: ```php $builder->add('address', 'form', array( 'virtual' => true, )); ``` After: ```php $builder->add('address', 'form', array( 'inherit_data' => true, )); ``` * The class `VirtualFormAwareIterator` was renamed to `InheritDataAwareIterator`. Before: ```php use Symfony\Component\Form\Util\VirtualFormAwareIterator; $iterator = new VirtualFormAwareIterator($forms); ``` After: ```php use Symfony\Component\Form\Util\InheritDataAwareIterator; $iterator = new InheritDataAwareIterator($forms); ``` * The `TypeTestCase` class was moved from the `Symfony\Component\Form\Tests\Extension\Core\Type` namespace to the `Symfony\Component\Form\Test` namespace. Before: ```php use Symfony\Component\Form\Tests\Extension\Core\Type\TypeTestCase class MyTypeTest extends TypeTestCase { // ... } ``` After: ```php use Symfony\Component\Form\Test\TypeTestCase; class MyTypeTest extends TypeTestCase { // ... } ``` * The `FormIntegrationTestCase` and `FormPerformanceTestCase` classes were moved form the `Symfony\Component\Form\Tests` namespace to the `Symfony\Component\Form\Test` namespace. * The constants `ROUND_HALFEVEN`, `ROUND_HALFUP` and `ROUND_HALFDOWN` in class `NumberToLocalizedStringTransformer` were renamed to `ROUND_HALF_EVEN`, `ROUND_HALF_UP` and `ROUND_HALF_DOWN`. * The `Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface` was removed in favor of `Symfony\Component\Form\ChoiceList\ChoiceListInterface`. * `Symfony\Component\Form\Extension\Core\View\ChoiceView` was removed in favor of `Symfony\Component\Form\ChoiceList\View\ChoiceView`. * The interface `Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface` and all of its implementations were removed. Use the new interface `Symfony\Component\Security\Csrf\CsrfTokenManagerInterface` instead. * The options "`csrf_provider`" and "`intention`" were renamed to "`csrf_token_generator`" and "`csrf_token_id`". * The method `Form::getErrorsAsString()` was removed. Use `Form::getErrors()` instead with the argument `$deep` set to true and `$flatten` set to false and cast the returned iterator to a string (if not done implicitly by PHP). Before: ```php echo $form->getErrorsAsString(); ``` After: ```php echo $form->getErrors(true, false); ``` * The `Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList` class has been removed in favor of `Symfony\Component\Form\ChoiceList\ArrayChoiceList`. * The `Symfony\Component\Form\Extension\Core\ChoiceList\LazyChoiceList` class has been removed in favor of `Symfony\Component\Form\ChoiceList\LazyChoiceList`. * The `Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList` class has been removed in favor of `Symfony\Component\Form\ChoiceList\ArrayChoiceList`. * The `Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList` class has been removed in favor of `Symfony\Component\Form\ChoiceList\ArrayChoiceList`. ### FrameworkBundle * The `config:debug`, `container:debug`, `router:debug`, `translation:debug` and `yaml:lint` commands have been deprecated since Symfony 2.7 and will be removed in Symfony 3.0. Use the `debug:config`, `debug:container`, `debug:router`, `debug:translation` and `lint:yaml` commands instead. * 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. Before: ```php namespace Acme\FooBundle\Controller; class DemoController { public function showAction() { $request = $this->getRequest(); // ... } } ``` After: ```php namespace Acme\FooBundle\Controller; use Symfony\Component\HttpFoundation\Request; class DemoController { public function showAction(Request $request) { // ... } } ``` * The `request` service was removed. You must inject the `request_stack` service instead. * The `enctype` method of the `form` helper was removed. You should use the new method `start` instead. Before: ```php
``` After: ```php start($form) ?> ... end($form) ?> ``` The method and action of the form default to "POST" and the current document. If you want to change these values, you can set them explicitly in the controller. Alternative 1: ```php $form = $this->createForm('my_form', $formData, array( 'method' => 'PUT', 'action' => $this->generateUrl('target_route'), )); ``` Alternative 2: ```php $form = $this->createFormBuilder($formData) // ... ->setMethod('PUT') ->setAction($this->generateUrl('target_route')) ->getForm(); ``` It is also possible to override the method and the action in the template: ```php start($form, array('method' => 'GET', 'action' => 'http://example.com')) ?> ... end($form) ?> ``` * The `RouterApacheDumperCommand` was removed. * The `templating.helper.router` service was moved to `templating_php.xml`. You have to ensure that the PHP templating engine is enabled to be able to use it: ```yaml framework: templating: engines: ['php'] ``` * 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. ### HttpKernel * The `Symfony\Component\HttpKernel\Log\LoggerInterface` has been removed in favor of `Psr\Log\LoggerInterface`. The only difference is that some method names are different: | Old name | New name | -------- | --- | `emerg()` | `emergency()` | `crit()` | `critical()` | `err()` | `error()` | `warn()` | `warning()` The previous method renames also happened to the following classes: * `Symfony\Bridge\Monolog\Logger` * `Symfony\Component\HttpKernel\Log\NullLogger` * The `Symfony\Component\HttpKernel\Kernel::init()` method has been removed. * The following classes have been renamed as they have been moved to the Debug component: | Old name | New name | -------- | --- | `Symfony\Component\HttpKernel\Debug\ErrorHandler` | `Symfony\Component\Debug\ErrorHandler` | `Symfony\Component\HttpKernel\Debug\ExceptionHandler` | `Symfony\Component\Debug\ExceptionHandler` | `Symfony\Component\HttpKernel\Exception\FatalErrorException` | `Symfony\Component\Debug\Exception\FatalErrorException` | `Symfony\Component\HttpKernel\Exception\FlattenException` | `Symfony\Component\Debug\Exception\FlattenException` * The `Symfony\Component\HttpKernel\EventListener\ExceptionListener` now passes the Request format as the `_format` argument instead of `format`. * The `Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass` has been renamed to `Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass` and moved to the EventDispatcher component. ### Locale * The Locale component was removed and replaced by the Intl component. Instead of the methods in `Symfony\Component\Locale\Locale`, you should use these equivalent methods in `Symfony\Component\Intl\Intl` now: | Old way | New way | ------- | --- | `Locale::getDisplayCountries()` | `Intl::getRegionBundle()->getCountryNames()` | `Locale::getCountries()` | `array_keys(Intl::getRegionBundle()->getCountryNames())` | `Locale::getDisplayLanguages()` | `Intl::getLanguageBundle()->getLanguageNames()` | `Locale::getLanguages()` | `array_keys(Intl::getLanguageBundle()->getLanguageNames())` | `Locale::getDisplayLocales()` | `Intl::getLocaleBundle()->getLocaleNames()` | `Locale::getLocales()` | `array_keys(Intl::getLocaleBundle()->getLocaleNames())` ### PropertyAccess * Renamed `PropertyAccess::getPropertyAccessor` to `createPropertyAccessor`. Before: ```php use Symfony\Component\PropertyAccess\PropertyAccess; $accessor = PropertyAccess::getPropertyAccessor(); ``` After: ```php use Symfony\Component\PropertyAccess\PropertyAccess; $accessor = PropertyAccess::createPropertyAccessor(); ``` ### Routing * Some route settings have been renamed: * The `pattern` setting has been removed in favor of `path` * The `_scheme` and `_method` requirements have been moved to the `schemes` and `methods` settings Before: ```yaml article_edit: pattern: /article/{id} requirements: { '_method': 'POST|PUT', '_scheme': 'https', 'id': '\d+' } ``` ```xml