1UPGRADE FROM 2.x to 3.0
2=======================
3
4# Table of Contents
5
6- [ClassLoader](#classloader)
7- [Config](#config)
8- [Console](#console)
9- [DependencyInjection](#dependencyinjection)
10- [DoctrineBridge](#doctrinebridge)
11- [DomCrawler](#domcrawler)
12- [EventDispatcher](#eventdispatcher)
13- [Form](#form)
14- [FrameworkBundle](#frameworkbundle)
15- [HttpFoundation](#httpfoundation)
16- [HttpKernel](#httpkernel)
17- [Locale](#locale)
18- [Monolog Bridge](#monolog-bridge)
19- [Process](#process)
20- [PropertyAccess](#propertyaccess)
21- [Routing](#routing)
22- [Security](#security)
23- [SecurityBundle](#securitybundle)
24- [Serializer](#serializer)
25- [Swiftmailer Bridge](#swiftmailer-bridge)
26- [Translator](#translator)
27- [Twig Bridge](#twig-bridge)
28- [TwigBundle](#twigbundle)
29- [Validator](#validator)
30- [WebProfiler](#webprofiler)
31- [Yaml](#yaml)
32
33### ClassLoader
34
35 * The `UniversalClassLoader` class has been removed in favor of
36   `ClassLoader`. The only difference is that some method names are different:
37
38   | Old name | New name
39   | -------- | ---
40   | `registerNamespaces()` | `addPrefixes()`
41   | `registerPrefixes()` | `addPrefixes()`
42   | `registerNamespace()` | `addPrefix()`
43   | `registerPrefix()` | `addPrefix()`
44   | `getNamespaces()` | `getPrefixes()`
45   | `getNamespaceFallbacks()` | `getFallbackDirs()`
46   | `getPrefixFallbacks()` | `getFallbackDirs()`
47
48 * The `DebugUniversalClassLoader` class has been removed in favor of
49   `DebugClassLoader`. The difference is that the constructor now takes a
50   loader to wrap.
51
52### Config
53
54 * `\Symfony\Component\Config\Resource\ResourceInterface::isFresh()` has been removed. Also,
55   cache validation through this method (which was still supported in 2.8 for BC) does no longer
56   work because the `\Symfony\Component\Config\Resource\BCResourceInterfaceChecker` helper class
57   has been removed as well.
58
59 * The `__toString()` method of the `\Symfony\Component\Config\ConfigCache` class
60   was removed in favor of the new `getPath()` method.
61
62### Console
63
64 * The `dialog` helper has been removed in favor of the `question` helper.
65
66 * The methods `isQuiet`, `isVerbose`, `isVeryVerbose` and `isDebug` were added
67   to `Symfony\Component\Console\Output\OutputInterface`.
68
69 * `ProgressHelper` has been removed in favor of `ProgressBar`.
70
71   Before:
72
73   ```php
74   $h = new ProgressHelper();
75   $h->start($output, 10);
76   for ($i = 1; $i < 5; $i++) {
77       usleep(200000);
78       $h->advance();
79   }
80   $h->finish();
81   ```
82
83   After:
84
85   ```php
86   $bar = new ProgressBar($output, 10);
87   $bar->start();
88   for ($i = 1; $i < 5; $i++) {
89       usleep(200000);
90       $bar->advance();
91   }
92   ```
93
94 * `TableHelper` has been removed in favor of `Table`.
95
96   Before:
97
98   ```php
99   $table = $app->getHelperSet()->get('table');
100   $table
101       ->setHeaders(array('ISBN', 'Title', 'Author'))
102       ->setRows(array(
103           array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
104           array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'),
105           array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
106           array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
107       ))
108   ;
109   $table->render($output);
110   ```
111
112   After:
113
114   ```php
115   use Symfony\Component\Console\Helper\Table;
116
117   $table = new Table($output);
118   $table
119       ->setHeaders(array('ISBN', 'Title', 'Author'))
120       ->setRows(array(
121           array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
122           array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'),
123           array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
124           array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
125       ))
126   ;
127   $table->render();
128   ```
129
130* Parameters of `renderException()` method of the
131  `Symfony\Component\Console\Application` are type hinted.
132  You must add the type hint to your implementations.
133
134### DependencyInjection
135
136 * The method `remove` was added to `Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface`.
137
138 * The concept of scopes was removed, the removed methods are:
139
140    - `Symfony\Component\DependencyInjection\ContainerBuilder::getScopes()`
141    - `Symfony\Component\DependencyInjection\ContainerBuilder::getScopeChildren()`
142    - `Symfony\Component\DependencyInjection\ContainerInterface::enterScope()`
143    - `Symfony\Component\DependencyInjection\ContainerInterface::leaveScope()`
144    - `Symfony\Component\DependencyInjection\ContainerInterface::addScope()`
145    - `Symfony\Component\DependencyInjection\ContainerInterface::hasScope()`
146    - `Symfony\Component\DependencyInjection\ContainerInterface::isScopeActive()`
147    - `Symfony\Component\DependencyInjection\Definition::setScope()`
148    - `Symfony\Component\DependencyInjection\Definition::getScope()`
149    - `Symfony\Component\DependencyInjection\Reference::isStrict()`
150
151  Also, the `$scope` and `$strict` parameters of `Symfony\Component\DependencyInjection\ContainerInterface::set()`
152  and `Symfony\Component\DependencyInjection\Reference` respectively were removed.
153
154 * A new `shared` flag has been added to the service definition
155   in replacement of the `prototype` scope.
156
157   Before:
158
159   ```php
160   use Symfony\Component\DependencyInjection\ContainerBuilder;
161
162   $container = new ContainerBuilder();
163   $container
164       ->register('foo', 'stdClass')
165       ->setScope(ContainerBuilder::SCOPE_PROTOTYPE)
166   ;
167   ```
168
169   ```yml
170   services:
171       foo:
172           class: stdClass
173           scope: prototype
174   ```
175
176   ```xml
177   <services>
178       <service id="foo" class="stdClass" scope="prototype" />
179   </services>
180   ```
181
182   After:
183
184   ```php
185   use Symfony\Component\DependencyInjection\ContainerBuilder;
186
187   $container = new ContainerBuilder();
188   $container
189       ->register('foo', 'stdClass')
190       ->setShared(false)
191   ;
192   ```
193
194   ```yml
195   services:
196       foo:
197           class: stdClass
198           shared: false
199   ```
200
201   ```xml
202   <services>
203       <service id="foo" class="stdClass" shared="false" />
204   </services>
205   ```
206
207 * `Symfony\Component\DependencyInjection\ContainerAware` was removed, use
208   `Symfony\Component\DependencyInjection\ContainerAwareTrait` or implement
209   `Symfony\Component\DependencyInjection\ContainerAwareInterface` manually
210
211 * The methods `Definition::setFactoryClass()`,
212   `Definition::setFactoryMethod()`, and `Definition::setFactoryService()` have
213   been removed in favor of `Definition::setFactory()`. Services defined using
214   YAML or XML use the same syntax as configurators.
215
216 * Synchronized services are deprecated and the following methods have been
217   removed: `ContainerBuilder::synchronize()`, `Definition::isSynchronized()`,
218   and `Definition::setSynchronized()`.
219
220### DomCrawler
221
222 * The interface of the `Symfony\Component\DomCrawler\Crawler` changed. It does no longer implement `\Iterator` but `\IteratorAggregate`. If you rely on methods of the `\Iterator` interface, call the `getIterator` method of the `\IteratorAggregate` interface before. No changes are required in a `\Traversable`-aware control structure, such as `foreach`.
223
224   Before:
225
226   ```php
227   $crawler->current();
228   ```
229
230   After:
231
232   ```php
233   $crawler->getIterator()->current();
234   ```
235
236### DoctrineBridge
237
238 * The `property` option of `DoctrineType` was removed in favor of the `choice_label` option.
239
240 * The `loader` option of `DoctrineType` was removed. You now have to override the `getLoader()`
241   method in your custom type.
242
243 * The `Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList` was removed in favor
244   of `Symfony\Bridge\Doctrine\Form\ChoiceList\DoctrineChoiceLoader`.
245
246 * Passing a query builder closure to `ORMQueryBuilderLoader` is not supported anymore.
247   You should pass resolved query builders only.
248
249   Consequently, the arguments `$manager` and `$class` of `ORMQueryBuilderLoader`
250   have been removed as well.
251
252   Note that the `query_builder` option of `DoctrineType` *does* support
253   closures, but the closure is now resolved in the type instead of in the
254   loader.
255
256 * Using the entity provider with a Doctrine repository implementing `UserProviderInterface` is not supported anymore.
257   You should make the repository implement `UserLoaderInterface` instead.
258
259### EventDispatcher
260
261 * The method `getListenerPriority($eventName, $listener)` has been added to the
262   `EventDispatcherInterface`.
263 * The interface `Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface`
264   extends `Symfony\Component\EventDispatcher\EventDispatcherInterface`.
265
266### Form
267
268 * The `getBlockPrefix()` method was added to the `FormTypeInterface` in replacement of
269   the `getName()` method which has been removed.
270
271 * The `configureOptions()` method was added to the `FormTypeInterface` in replacement
272   of the `setDefaultOptions()` method which has been removed.
273
274 * The `getBlockPrefix()` method was added to the `ResolvedFormTypeInterface` in
275   replacement of the `getName()` method which has been removed.
276
277 * The option `options` of the `CollectionType` has been removed in favor
278   of the `entry_options` option.
279
280 * The `cascade_validation` option was removed. Use the `constraints` option
281   together with the `Valid` constraint instead.
282
283 * Type names were removed. Instead of referencing types by name, you must
284   reference them by their fully-qualified class name (FQCN) instead:
285
286   Before:
287
288   ```php
289   $form = $this->createFormBuilder()
290       ->add('name', 'text')
291       ->add('age', 'integer')
292       ->getForm();
293   ```
294
295   After:
296
297   ```php
298   use Symfony\Component\Form\Extension\Core\Type\IntegerType;
299   use Symfony\Component\Form\Extension\Core\Type\TextType;
300
301   $form = $this->createFormBuilder()
302       ->add('name', TextType::class)
303       ->add('age', IntegerType::class)
304       ->getForm();
305   ```
306
307   If you want to customize the block prefix of a type in Twig, you must now
308   implement `FormTypeInterface::getBlockPrefix()`:
309
310   Before:
311
312   ```php
313   class UserProfileType extends AbstractType
314   {
315       public function getName()
316       {
317           return 'profile';
318       }
319   }
320   ```
321
322   After:
323
324   ```php
325   class UserProfileType extends AbstractType
326   {
327       public function getBlockPrefix()
328       {
329           return 'profile';
330       }
331   }
332   ```
333
334   If you don't customize `getBlockPrefix()`, it defaults to the class name
335   without "Type" suffix in underscore notation (here: "user_profile").
336
337   Type extension must return the fully-qualified class name of the extended
338   type from `FormTypeExtensionInterface::getExtendedType()` now.
339
340   Before:
341
342   ```php
343   class MyTypeExtension extends AbstractTypeExtension
344   {
345       public function getExtendedType()
346       {
347           return 'form';
348       }
349   }
350   ```
351
352   After:
353
354   ```php
355   use Symfony\Component\Form\Extension\Core\Type\FormType;
356
357   class MyTypeExtension extends AbstractTypeExtension
358   {
359       public function getExtendedType()
360       {
361           return FormType::class;
362       }
363   }
364   ```
365
366 * The `FormTypeInterface::getName()` method was removed.
367
368 * Returning type instances from `FormTypeInterface::getParent()` is not
369   supported anymore. Return the fully-qualified class name of the parent
370   type class instead.
371
372   Before:
373
374   ```php
375   class MyType
376   {
377       public function getParent()
378       {
379           return new ParentType();
380       }
381   }
382   ```
383
384   After:
385
386   ```php
387   class MyType
388   {
389       public function getParent()
390       {
391           return ParentType::class;
392       }
393   }
394   ```
395
396 * The option `type` of the `CollectionType` has been removed in favor of
397   the `entry_type` option. The value for the `entry_type` option must be
398   the fully-qualified class name (FQCN).
399
400 * Passing type instances to `Form::add()`, `FormBuilder::add()` and the
401   `FormFactory::create*()` methods is not supported anymore. Pass the
402   fully-qualified class name of the type instead.
403
404   Before:
405
406   ```php
407   $form = $this->createForm(new MyType());
408   ```
409
410   After:
411
412   ```php
413   $form = $this->createForm(MyType::class);
414   ```
415
416 * Passing custom data to forms now needs to be done
417   through the options resolver.
418
419    In the controller:
420
421    Before:
422    ```php
423    $form = $this->createForm(new MyType($variable), $entity, array(
424        'action' => $this->generateUrl('action_route'),
425        'method' => 'PUT',
426    ));
427    ```
428    After:
429    ```php
430    $form = $this->createForm(MyType::class, $entity, array(
431        'action' => $this->generateUrl('action_route'),
432        'method' => 'PUT',
433        'custom_value' => $variable,
434    ));
435    ```
436    In the form type:
437
438    Before:
439    ```php
440    class MyType extends AbstractType
441    {
442        private $value;
443
444        public function __construct($variableValue)
445        {
446            $this->value = $value;
447        }
448        // ...
449    }
450    ```
451
452    After:
453    ```php
454    public function buildForm(FormBuilderInterface $builder, array $options)
455    {
456        $value = $options['custom_value'];
457        // ...
458    }
459
460    public function configureOptions(OptionsResolver $resolver)
461    {
462        $resolver->setDefaults(array(
463            'custom_value' => null,
464        ));
465    }
466    ```
467
468 * The alias option of the `form.type_extension` tag was removed in favor of
469   the `extended_type`/`extended-type` option.
470
471   Before:
472   ```xml
473   <service id="app.type_extension" class="Vendor\Form\Extension\MyTypeExtension">
474       <tag name="form.type_extension" alias="text" />
475   </service>
476   ```
477
478   After:
479   ```xml
480   <service id="app.type_extension" class="Vendor\Form\Extension\MyTypeExtension">
481       <tag name="form.type_extension" extended-type="Symfony\Component\Form\Extension\Core\Type\TextType" />
482   </service>
483   ```
484
485 * The `max_length` option was removed. Use the `attr` option instead by setting it to
486   an `array` with a `maxlength` key.
487
488 * The `ChoiceToBooleanArrayTransformer`, `ChoicesToBooleanArrayTransformer`,
489   `FixRadioInputListener`, and `FixCheckboxInputListener` classes were removed.
490
491 * The `choice_list` option of `ChoiceType` was removed.
492
493 * The option "precision" was renamed to "scale".
494
495   Before:
496
497   ```php
498   use Symfony\Component\Form\Extension\Core\Type\NumberType;
499
500   $builder->add('length', NumberType::class, array(
501      'precision' => 3,
502   ));
503   ```
504
505   After:
506
507   ```php
508   use Symfony\Component\Form\Extension\Core\Type\NumberType;
509
510   $builder->add('length', NumberType::class, array(
511      'scale' => 3,
512   ));
513   ```
514
515 * The option "`virtual`" was renamed to "`inherit_data`".
516
517   Before:
518
519   ```php
520   use Symfony\Component\Form\Extension\Core\Type\FormType;
521
522   $builder->add('address', FormType::class, array(
523       'virtual' => true,
524   ));
525   ```
526
527   After:
528
529   ```php
530   use Symfony\Component\Form\Extension\Core\Type\FormType;
531
532   $builder->add('address', FormType::class, array(
533       'inherit_data' => true,
534   ));
535   ```
536
537 * The method `AbstractType::setDefaultOptions(OptionsResolverInterface $resolver)` and
538   `AbstractTypeExtension::setDefaultOptions(OptionsResolverInterface $resolver)` have been
539   renamed. You should use `AbstractType::configureOptions(OptionsResolver $resolver)` and
540   `AbstractTypeExtension::configureOptions(OptionsResolver $resolver)` instead.
541
542 * The methods `Form::bind()` and `Form::isBound()` were removed. You should
543   use `Form::submit()` and `Form::isSubmitted()` instead.
544
545   Before:
546
547   ```php
548   $form->bind(array(...));
549   ```
550
551   After:
552
553   ```php
554   $form->submit(array(...));
555   ```
556
557 * Passing a `Symfony\Component\HttpFoundation\Request` instance, as was
558   supported by `FormInterface::bind()`, is not possible with
559   `FormInterface::submit()` anymore. You should use `FormInterface::handleRequest()`
560   instead.
561
562   Before:
563
564   ```php
565   if ('POST' === $request->getMethod()) {
566       $form->bind($request);
567
568       if ($form->isValid()) {
569           // ...
570       }
571   }
572   ```
573
574   After:
575
576   ```php
577   $form->handleRequest($request);
578
579   if ($form->isValid()) {
580       // ...
581   }
582   ```
583
584   If you want to test whether the form was submitted separately, you can use
585   the method `isSubmitted()`:
586
587   ```php
588   $form->handleRequest($request);
589
590   if ($form->isSubmitted()) {
591      // ...
592
593      if ($form->isValid()) {
594          // ...
595      }
596   }
597   ```
598
599   If the form is submitted with a different request method than `POST`, you need to configure this in the form:
600
601   Before:
602
603   ```php
604   $form = $this->createForm(FormType::class, $entity);
605   $form->submit($request);
606   ```
607
608   After:
609
610   ```php
611   $form = $this->createForm(FormType::class, $entity, [
612       'method' => 'PUT',
613   ]);
614   $form->handleRequest($request);
615   ```
616
617 * The events `PRE_BIND`, `BIND` and `POST_BIND` were renamed to `PRE_SUBMIT`, `SUBMIT`
618   and `POST_SUBMIT`.
619
620   Before:
621
622   ```php
623   $builder->addEventListener(FormEvents::PRE_BIND, function (FormEvent $event) {
624       // ...
625   });
626   ```
627
628   After:
629
630   ```php
631   $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
632       // ...
633   });
634   ```
635
636 * The class `VirtualFormAwareIterator` was renamed to `InheritDataAwareIterator`.
637
638   Before:
639
640   ```php
641   use Symfony\Component\Form\Util\VirtualFormAwareIterator;
642
643   $iterator = new VirtualFormAwareIterator($forms);
644   ```
645
646   After:
647
648   ```php
649   use Symfony\Component\Form\Util\InheritDataAwareIterator;
650
651   $iterator = new InheritDataAwareIterator($forms);
652   ```
653
654 * The `TypeTestCase` class was moved from the `Symfony\Component\Form\Tests\Extension\Core\Type` namespace to the `Symfony\Component\Form\Test` namespace.
655
656   Before:
657
658   ```php
659   use Symfony\Component\Form\Tests\Extension\Core\Type\TypeTestCase
660
661   class MyTypeTest extends TypeTestCase
662   {
663       // ...
664   }
665   ```
666
667   After:
668
669   ```php
670   use Symfony\Component\Form\Test\TypeTestCase;
671
672   class MyTypeTest extends TypeTestCase
673   {
674       // ...
675   }
676   ```
677
678 * The option "options" of the CollectionType has been renamed to "entry_options".
679
680 * The option "type" of the CollectionType has been renamed to "entry_type".
681   As a value for the option you must provide the fully-qualified class name (FQCN)
682   now as well.
683
684 * The `FormIntegrationTestCase` and `FormPerformanceTestCase` classes were moved from the `Symfony\Component\Form\Tests` namespace to the `Symfony\Component\Form\Test` namespace.
685
686 * The constants `ROUND_HALFEVEN`, `ROUND_HALFUP` and `ROUND_HALFDOWN` in class
687   `NumberToLocalizedStringTransformer` were renamed to `ROUND_HALF_EVEN`,
688   `ROUND_HALF_UP` and `ROUND_HALF_DOWN`.
689
690 * The `Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface` was
691   removed in favor of `Symfony\Component\Form\ChoiceList\ChoiceListInterface`.
692
693 * `Symfony\Component\Form\Extension\Core\View\ChoiceView` was removed in favor of
694   `Symfony\Component\Form\ChoiceList\View\ChoiceView`.
695
696 * The interface `Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface`
697   and all of its implementations were removed. Use the new interface
698   `Symfony\Component\Security\Csrf\CsrfTokenManagerInterface` instead.
699
700 * The options "`csrf_provider`" and "`intention`" were renamed to  "`csrf_token_generator`"
701   and "`csrf_token_id`".
702
703 * The method `Form::getErrorsAsString()` was removed. Use `Form::getErrors()`
704   instead with the argument `$deep` set to true and `$flatten` set to false
705   and cast the returned iterator to a string (if not done implicitly by PHP).
706
707   Before:
708
709   ```php
710   echo $form->getErrorsAsString();
711   ```
712
713   After:
714
715   ```php
716   echo $form->getErrors(true, false);
717   ```
718
719 * The `Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList` class has been removed in
720   favor of `Symfony\Component\Form\ChoiceList\ArrayChoiceList`.
721
722 * The `Symfony\Component\Form\Extension\Core\ChoiceList\LazyChoiceList` class has been removed in
723   favor of `Symfony\Component\Form\ChoiceList\LazyChoiceList`.
724
725 * The `Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList` class has been removed in
726   favor of `Symfony\Component\Form\ChoiceList\ArrayChoiceList`.
727
728 * The `Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList` class has been removed in
729   favor of `Symfony\Component\Form\ChoiceList\ArrayChoiceList`.
730
731 * The `TimezoneType::getTimezones()` method was removed. You should not use
732   this method.
733
734 * The `Symfony\Component\Form\ChoiceList\ArrayKeyChoiceList` class has been removed in
735   favor of `Symfony\Component\Form\ChoiceList\ArrayChoiceList`.
736
737### FrameworkBundle
738
739 * The `config:debug`, `container:debug`, `router:debug`, `translation:debug`
740   and `yaml:lint` commands have been deprecated since Symfony 2.7 and will
741   be removed in Symfony 3.0. Use the `debug:config`, `debug:container`,
742   `debug:router`, `debug:translation` and `lint:yaml` commands instead.
743
744 * The base `Controller`class is now abstract.
745
746 * The visibility of all methods of the base `Controller` class has been changed from
747   `public` to `protected`.
748
749 * The `getRequest` method of the base `Controller` class has been deprecated
750   since Symfony 2.4 and must be therefore removed in 3.0. The only reliable
751   way to get the `Request` object is to inject it in the action method.
752
753   Before:
754
755   ```php
756   namespace Acme\FooBundle\Controller;
757
758   class DemoController
759   {
760       public function showAction()
761       {
762           $request = $this->getRequest();
763           // ...
764       }
765   }
766   ```
767
768   After:
769
770   ```php
771   namespace Acme\FooBundle\Controller;
772
773   use Symfony\Component\HttpFoundation\Request;
774
775   class DemoController
776   {
777       public function showAction(Request $request)
778       {
779           // ...
780       }
781   }
782   ```
783
784 * In Symfony 2.7 a small BC break was introduced with the new choices_as_values
785   option. In order to have the choice values populated to the html value attribute
786   you had to define the choice_value option. This is now not any more needed.
787
788   Before:
789
790   ```php
791   $form->add('status', 'choice', array(
792       'choices' => array(
793           'Enabled' => Status::ENABLED,
794           'Disabled' => Status::DISABLED,
795           'Ignored' => Status::IGNORED,
796       ),
797       // choices_as_values defaults to true in Symfony 3.0
798       // and setting it to anything else is deprecated as of 3.0
799       'choices_as_values' => true,
800       // important if you rely on your option value attribute (e.g. for JavaScript)
801       // this will keep the same functionality as before
802       'choice_value' => function ($choice) {
803           return $choice;
804       },
805   ));
806   ```
807
808   After:
809
810   ```php
811   $form->add('status', ChoiceType::class, array(
812       'choices' => array(
813           'Enabled' => Status::ENABLED,
814           'Disabled' => Status::DISABLED,
815           'Ignored' => Status::IGNORED,
816       )
817   ));
818   ```
819
820 * The `request` service was removed. You must inject the `request_stack`
821   service instead.
822
823 * The `enctype` method of the `form` helper was removed. You should use the
824   new method `start` instead.
825
826   Before:
827
828   ```php
829   <form method="post" action="http://example.com" <?php echo $view['form']->enctype($form) ?>>
830       ...
831   </form>
832   ```
833
834   After:
835
836   ```php
837   <?php echo $view['form']->start($form) ?>
838       ...
839   <?php echo $view['form']->end($form) ?>
840   ```
841
842   The method and action of the form default to "POST" and the current
843   document. If you want to change these values, you can set them explicitly in
844   the controller.
845
846   Alternative 1:
847
848   ```php
849   $form = $this->createForm('my_form', $formData, array(
850       'method' => 'PUT',
851       'action' => $this->generateUrl('target_route'),
852   ));
853   ```
854
855   Alternative 2:
856
857   ```php
858   $form = $this->createFormBuilder($formData)
859       // ...
860       ->setMethod('PUT')
861       ->setAction($this->generateUrl('target_route'))
862       ->getForm();
863   ```
864
865   It is also possible to override the method and the action in the template:
866
867   ```php
868   <?php echo $view['form']->start($form, array('method' => 'GET', 'action' => 'http://example.com')) ?>
869       ...
870   <?php echo $view['form']->end($form) ?>
871   ```
872
873 * The `RouterApacheDumperCommand` was removed.
874
875 * The `createEsi` method of `Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache` was removed. Use `createSurrogate` instead.
876
877 * The `templating.helper.router` service was moved to `templating_php.xml`. You
878   have to ensure that the PHP templating engine is enabled to be able to use it:
879
880   ```yaml
881   framework:
882       templating:
883           engines: ['php']
884   ```
885
886 * The assets settings under `framework.templating` were moved to `framework.assets`.
887
888   Before:
889
890   ```yml
891   framework:
892       templating:
893           assets_version: 'v123'
894           assets_version_format: '%%s?version=%%s'
895           assets_base_urls:
896               http: ['http://cdn.example.com']
897               ssl:  ['https://secure.example.com']
898           packages:
899               # ...
900   ```
901
902   After:
903
904   ```yml
905   framework:
906       assets:
907           version: 'v123'
908           version_format: '%%s?version=%%s'
909           base_urls: ['http://cdn.example.com', 'https://secure.example.com']
910           packages:
911               # ...
912   ```
913
914 * The `form.csrf_provider` service is removed as it implements an adapter for
915   the new token manager to the deprecated
916   `Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface`
917   interface.
918   The `security.csrf.token_manager` should be used instead.
919
920 * The `validator.mapping.cache.apc` service has been removed in favor of the `validator.mapping.cache.doctrine.apc` one.
921
922 * The ability to pass `apc` as the `framework.validation.cache` configuration key value has been removed.
923   Use `validator.mapping.cache.doctrine.apc` instead:
924
925   Before:
926
927   ```yaml
928   framework:
929       validation:
930           cache: apc
931   ```
932
933   After:
934
935   ```yaml
936   framework:
937       validation:
938           cache: validator.mapping.cache.doctrine.apc
939   ```
940
941### HttpKernel
942
943 * The `Symfony\Component\HttpKernel\Log\LoggerInterface` has been removed in
944   favor of `Psr\Log\LoggerInterface`. The only difference is that some method
945   names are different:
946
947   | Old name | New name
948   | -------- | ---
949   | `emerg()` | `emergency()`
950   | `crit()` | `critical()`
951   | `err()` | `error()`
952   | `warn()` | `warning()`
953
954   The previous method renames also happened to the following classes:
955
956     * `Symfony\Bridge\Monolog\Logger`
957     * `Symfony\Component\HttpKernel\Log\NullLogger`
958
959 * The `Symfony\Component\HttpKernel\Kernel::init()` method has been removed.
960
961 * The following classes have been renamed as they have been moved to the
962   Debug component:
963
964   | Old name | New name
965   | -------- | ---
966   | `Symfony\Component\HttpKernel\Debug\ErrorHandler` | `Symfony\Component\Debug\ErrorHandler`
967   | `Symfony\Component\HttpKernel\Debug\ExceptionHandler` | `Symfony\Component\Debug\ExceptionHandler`
968   | `Symfony\Component\HttpKernel\Exception\FatalErrorException` | `Symfony\Component\Debug\Exception\FatalErrorException`
969   | `Symfony\Component\HttpKernel\Exception\FlattenException` | `Symfony\Component\Debug\Exception\FlattenException`
970
971 * The `Symfony\Component\HttpKernel\EventListener\ExceptionListener` now
972   passes the Request format as the `_format` argument instead of `format`.
973
974 * The `Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass` has been renamed to
975   `Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass` and moved to the EventDispatcher component.
976
977### Locale
978
979 * The Locale component was removed and replaced by the Intl component.
980   Instead of the methods in `Symfony\Component\Locale\Locale`, you should use
981   these equivalent methods in `Symfony\Component\Intl\Intl` now:
982
983   | Old way | New way
984   | ------- | ---
985   | `Locale::getDisplayCountries()` | `Intl::getRegionBundle()->getCountryNames()`
986   | `Locale::getCountries()` | `array_keys(Intl::getRegionBundle()->getCountryNames())`
987   | `Locale::getDisplayLanguages()` | `Intl::getLanguageBundle()->getLanguageNames()`
988   | `Locale::getLanguages()` | `array_keys(Intl::getLanguageBundle()->getLanguageNames())`
989   | `Locale::getDisplayLocales()` | `Intl::getLocaleBundle()->getLocaleNames()`
990   | `Locale::getLocales()` | `array_keys(Intl::getLocaleBundle()->getLocaleNames())`
991
992### PropertyAccess
993
994 * Renamed `PropertyAccess::getPropertyAccessor` to `createPropertyAccessor`.
995
996   Before:
997
998   ```php
999   use Symfony\Component\PropertyAccess\PropertyAccess;
1000
1001   $accessor = PropertyAccess::getPropertyAccessor();
1002   ```
1003
1004   After:
1005
1006   ```php
1007   use Symfony\Component\PropertyAccess\PropertyAccess;
1008
1009   $accessor = PropertyAccess::createPropertyAccessor();
1010   ```
1011
1012### Routing
1013
1014 * Some route settings have been renamed:
1015
1016     * The `pattern` setting has been removed in favor of `path`
1017     * The `_scheme` and `_method` requirements have been moved to the `schemes` and `methods` settings
1018
1019   Before:
1020
1021   ```yaml
1022   article_edit:
1023       pattern: /article/{id}
1024       requirements: { '_method': 'POST|PUT', '_scheme': 'https', 'id': '\d+' }
1025   ```
1026
1027   ```xml
1028   <route id="article_edit" pattern="/article/{id}">
1029       <requirement key="_method">POST|PUT</requirement>
1030       <requirement key="_scheme">https</requirement>
1031       <requirement key="id">\d+</requirement>
1032   </route>
1033   ```
1034
1035   ```php
1036   $route = new Route();
1037   $route->setPattern('/article/{id}');
1038   $route->setRequirement('_method', 'POST|PUT');
1039   $route->setRequirement('_scheme', 'https');
1040   ```
1041
1042   After:
1043
1044   ```yaml
1045   article_edit:
1046       path: /article/{id}
1047       methods: [POST, PUT]
1048       schemes: https
1049       requirements: { 'id': '\d+' }
1050   ```
1051
1052   ```xml
1053   <route id="article_edit" path="/article/{id}" methods="POST PUT" schemes="https">
1054       <requirement key="id">\d+</requirement>
1055   </route>
1056   ```
1057
1058   ```php
1059   $route = new Route();
1060   $route->setPath('/article/{id}');
1061   $route->setMethods(array('POST', 'PUT'));
1062   $route->setSchemes('https');
1063   ```
1064
1065 * The `ApacheMatcherDumper` and `ApacheUrlMatcher` were removed since
1066   the performance gains were minimal and it's hard to replicate the behavior
1067   of PHP implementation.
1068
1069 * The `getMatcherDumperInstance()` and `getGeneratorDumperInstance()` methods in the
1070   `Symfony\Component\Routing\Router` have been changed from `public` to `protected`.
1071
1072 * Use the constants defined in the UrlGeneratorInterface for the $referenceType argument of the UrlGeneratorInterface::generate method.
1073
1074   Before:
1075
1076   ```php
1077   // url generated in controller
1078   $this->generateUrl('blog_show', array('slug' => 'my-blog-post'), true);
1079
1080   // url generated in @router service
1081   $router->generate('blog_show', array('slug' => 'my-blog-post'), true);
1082   ```
1083
1084   After:
1085
1086   ```php
1087   use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
1088
1089   // url generated in controller
1090   $this->generateUrl('blog_show', array('slug' => 'my-blog-post'), UrlGeneratorInterface::ABSOLUTE_URL);
1091
1092   // url generated in @router service
1093   $router->generate('blog_show', array('slug' => 'my-blog-post'), UrlGeneratorInterface::ABSOLUTE_URL);
1094   ```
1095
1096### Security
1097
1098 * The `vote()` method from the `VoterInterface` was changed to now accept arbitrary
1099   types and not only objects. You can rely on the new abstract `Voter` class introduced
1100   in 2.8 to ease integrating your own voters.
1101
1102 * The `AbstractVoter` class was removed in favor of the new `Voter` class.
1103
1104 * The `Resources/` directory was moved to `Core/Resources/`
1105
1106 * The `key` settings of `anonymous`, `remember_me` and `http_digest` are
1107   renamed to `secret`.
1108
1109   Before:
1110
1111   ```yaml
1112   security:
1113       # ...
1114       firewalls:
1115           default:
1116               # ...
1117               anonymous: { key: "%secret%" }
1118               remember_me:
1119                   key: "%secret%"
1120               http_digest:
1121                   key: "%secret%"
1122   ```
1123
1124   ```xml
1125   <!-- ... -->
1126   <config>
1127       <!-- ... -->
1128
1129       <firewall>
1130           <!-- ... -->
1131
1132           <anonymous key="%secret%"/>
1133           <remember-me key="%secret%"/>
1134           <http-digest key="%secret%"/>
1135       </firewall>
1136   </config>
1137   ```
1138
1139   ```php
1140   // ...
1141   $container->loadFromExtension('security', array(
1142       // ...
1143       'firewalls' => array(
1144           // ...
1145           'anonymous' => array('key' => '%secret%'),
1146           'remember_me' => array('key' => '%secret%'),
1147           'http_digest' => array('key' => '%secret%'),
1148       ),
1149   ));
1150   ```
1151
1152   After:
1153
1154   ```yaml
1155   security:
1156       # ...
1157       firewalls:
1158           default:
1159               # ...
1160               anonymous: { secret: "%secret%" }
1161               remember_me:
1162                   secret: "%secret%"
1163               http_digest:
1164                   secret: "%secret%"
1165   ```
1166
1167   ```xml
1168   <!-- ... -->
1169   <config>
1170       <!-- ... -->
1171
1172       <firewall>
1173           <!-- ... -->
1174
1175           <anonymous secret="%secret%"/>
1176           <remember-me secret="%secret%"/>
1177           <http-digest secret="%secret%"/>
1178       </firewall>
1179   </config>
1180   ```
1181
1182   ```php
1183   // ...
1184   $container->loadFromExtension('security', array(
1185       // ...
1186       'firewalls' => array(
1187           // ...
1188           'anonymous' => array('secret' => '%secret%'),
1189           'remember_me' => array('secret' => '%secret%'),
1190           'http_digest' => array('secret' => '%secret%'),
1191       ),
1192   ));
1193   ```
1194
1195 * The `AbstractVoter` class was removed. Instead, extend the new `Voter` class,
1196   introduced in 2.8, and move your voting logic to the to the `supports($attribute, $subject)`
1197   and `voteOnAttribute($attribute, $object, TokenInterface $token)` methods.
1198
1199 * The `vote()` method from the `VoterInterface` was changed to now accept arbitrary
1200   types, and not only objects.
1201
1202 * The `supportsClass` and `supportsAttribute` methods were
1203   removed from the `VoterInterface` interface.
1204
1205   Before:
1206
1207   ```php
1208   class MyVoter extends AbstractVoter
1209   {
1210       protected function getSupportedAttributes()
1211       {
1212           return array('CREATE', 'EDIT');
1213       }
1214
1215       protected function getSupportedClasses()
1216       {
1217           return array('AppBundle\Entity\Post');
1218       }
1219
1220       // ...
1221   }
1222   ```
1223
1224   After:
1225
1226   ```php
1227   use Symfony\Component\Security\Core\Authorization\Voter\Voter;
1228
1229   class MyVoter extends Voter
1230   {
1231       protected function supports($attribute, $object)
1232       {
1233           return $object instanceof Post && in_array($attribute, array('CREATE', 'EDIT'));
1234       }
1235
1236       protected function voteOnAttribute($attribute, $object, TokenInterface $token)
1237       {
1238           // Return true or false
1239       }
1240   }
1241   ```
1242
1243 * The `AbstractVoter::isGranted()` method has been replaced by `Voter::voteOnAttribute()`.
1244
1245   Before:
1246
1247   ```php
1248   class MyVoter extends AbstractVoter
1249   {
1250       protected function isGranted($attribute, $object, $user = null)
1251       {
1252           return 'EDIT' === $attribute && $user === $object->getAuthor();
1253       }
1254
1255       // ...
1256   }
1257   ```
1258
1259   After:
1260
1261   ```php
1262   class MyVoter extends Voter
1263   {
1264       protected function voteOnAttribute($attribute, $object, TokenInterface $token)
1265       {
1266           return 'EDIT' === $attribute && $token->getUser() === $object->getAuthor();
1267       }
1268
1269       // ...
1270   }
1271   ```
1272
1273 * The `supportsAttribute()` and `supportsClass()` methods of the `AuthenticatedVoter`, `ExpressionVoter`,
1274   and `RoleVoter` classes have been removed.
1275
1276 * The `intention` option was renamed to `csrf_token_id` for all the authentication listeners.
1277
1278 * The `csrf_provider` option was renamed to `csrf_token_generator` for all the authentication listeners.
1279
1280### SecurityBundle
1281
1282 * The `intention` firewall listener setting was renamed to `csrf_token_id`.
1283
1284 * The `csrf_provider` firewall listener setting was renamed to `csrf_token_generator`.
1285
1286### Serializer
1287
1288 * The `setCamelizedAttributes()` method of the
1289   `Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer` and
1290   `Symfony\Component\Serializer\Normalizer\PropertyNormalizer` classes
1291   was removed.
1292
1293 * The `Symfony\Component\Serializer\Exception\Exception` interface was removed
1294   in favor of the new `Symfony\Component\Serializer\Exception\ExceptionInterface`.
1295
1296### Translator
1297
1298 * The `Translator::setFallbackLocale()` method has been removed in favor of
1299   `Translator::setFallbackLocales()`.
1300
1301 * The visibility of the `locale` property has been changed from protected to private. Rely on `getLocale` and `setLocale`
1302   instead.
1303
1304   Before:
1305
1306   ```php
1307    class CustomTranslator extends Translator
1308    {
1309        public function fooMethod()
1310        {
1311           // get locale
1312           $locale = $this->locale;
1313
1314           // update locale
1315           $this->locale = $locale;
1316        }
1317    }
1318   ```
1319
1320   After:
1321
1322   ```php
1323    class CustomTranslator extends Translator
1324    {
1325        public function fooMethod()
1326        {
1327           // get locale
1328           $locale = $this->getLocale();
1329
1330           // update locale
1331           $this->setLocale($locale);
1332       }
1333    }
1334   ```
1335
1336 * The method `FileDumper::format()` was removed. You should use
1337   `FileDumper::formatCatalogue()` instead.
1338
1339   Before:
1340
1341   ```php
1342    class CustomDumper extends FileDumper
1343    {
1344        protected function format(MessageCatalogue $messages, $domain)
1345        {
1346            ...
1347        }
1348    }
1349   ```
1350
1351   After:
1352
1353   ```php
1354    class CustomDumper extends FileDumper
1355    {
1356        public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array())
1357        {
1358            ...
1359        }
1360    }
1361   ```
1362
1363 * The `getMessages()` method of the `Symfony\Component\Translation\Translator`
1364   class was removed. You should use the `getCatalogue()` method of the
1365   `Symfony\Component\Translation\TranslatorBagInterface`.
1366
1367### Twig Bridge
1368
1369 * The `twig:lint` command has been deprecated since Symfony 2.7 and will be
1370   removed in Symfony 3.0. Use the `lint:twig` command instead.
1371
1372 * The `render` tag is deprecated in favor of the `render` function.
1373
1374 * The `form_enctype` helper was removed. You should use the new `form_start`
1375   function instead.
1376
1377   Before:
1378
1379   ```php
1380   <form method="post" action="http://example.com" {{ form_enctype(form) }}>
1381       ...
1382   </form>
1383   ```
1384
1385   After:
1386
1387   ```jinja
1388   {{ form_start(form) }}
1389       ...
1390   {{ form_end(form) }}
1391   ```
1392
1393   The method and action of the form default to "POST" and the current
1394   document. If you want to change these values, you can set them explicitly in
1395   the controller.
1396
1397   Alternative 1:
1398
1399   ```php
1400   $form = $this->createForm('my_form', $formData, array(
1401       'method' => 'PUT',
1402       'action' => $this->generateUrl('target_route'),
1403   ));
1404   ```
1405
1406   Alternative 2:
1407
1408   ```php
1409   $form = $this->createFormBuilder($formData)
1410       // ...
1411       ->setMethod('PUT')
1412       ->setAction($this->generateUrl('target_route'))
1413       ->getForm();
1414   ```
1415
1416   It is also possible to override the method and the action in the template:
1417
1418   ```jinja
1419   {{ form_start(form, {'method': 'GET', 'action': 'http://example.com'}) }}
1420       ...
1421   {{ form_end(form) }}
1422   ```
1423
1424### TwigBundle
1425
1426 * The `Symfony\Bundle\TwigBundle\TwigDefaultEscapingStrategy` was removed
1427   in favor of `Twig_FileExtensionEscapingStrategy`.
1428
1429 * The `twig:debug` command has been deprecated since Symfony 2.7 and will be
1430   removed in Symfony 3.0. Use the `debug:twig` command instead.
1431
1432### Validator
1433
1434 * The PHP7-incompatible constraints (`Null`, `True`, `False`) and their related
1435   validators (`NullValidator`, `TrueValidator`, `FalseValidator`) have been
1436   removed in favor of their `Is`-prefixed equivalent.
1437
1438 * The class `Symfony\Component\Validator\Mapping\Cache\ApcCache` has been removed in favor
1439   of `Symfony\Component\Validator\Mapping\Cache\DoctrineCache`.
1440
1441   Before:
1442
1443   ```php
1444   use Symfony\Component\Validator\Mapping\Cache\ApcCache;
1445
1446   $cache = new ApcCache('symfony.validator');
1447   ```
1448
1449   After:
1450
1451   ```php
1452   use Symfony\Component\Validator\Mapping\Cache\DoctrineCache;
1453   use Doctrine\Common\Cache\ApcCache;
1454
1455   $apcCache = new ApcCache();
1456   $apcCache->setNamespace('symfony.validator');
1457
1458   $cache = new DoctrineCache($apcCache);
1459   ```
1460
1461 * The constraints `Optional` and `Required` were moved to the
1462   `Symfony\Component\Validator\Constraints\` namespace. You should adapt
1463   the path wherever you used them.
1464
1465   Before:
1466
1467   ```php
1468   use Symfony\Component\Validator\Constraints as Assert;
1469
1470   /**
1471    * @Assert\Collection({
1472    *     "foo" = @Assert\Collection\Required(),
1473    *     "bar" = @Assert\Collection\Optional(),
1474    * })
1475    */
1476   private $property;
1477   ```
1478
1479   After:
1480
1481   ```php
1482   use Symfony\Component\Validator\Constraints as Assert;
1483
1484   /**
1485    * @Assert\Collection({
1486    *     "foo" = @Assert\Required(),
1487    *     "bar" = @Assert\Optional(),
1488    * })
1489    */
1490   private $property;
1491   ```
1492
1493 * The option "`methods`" of the `Callback` constraint was removed. You should
1494   use the option "`callback`" instead. If you have multiple callbacks, add
1495   multiple callback constraints instead.
1496
1497   Before (YAML):
1498
1499   ```yaml
1500   constraints:
1501     - Callback: [firstCallback, secondCallback]
1502   ```
1503
1504   After (YAML):
1505
1506   ```yaml
1507   constraints:
1508     - Callback: firstCallback
1509     - Callback: secondCallback
1510   ```
1511
1512   When using annotations, you can now put the `Callback` constraint directly on
1513   the method that should be executed.
1514
1515   Before (Annotations):
1516
1517   ```php
1518   use Symfony\Component\Validator\Constraints as Assert;
1519   use Symfony\Component\Validator\ExecutionContextInterface;
1520
1521   /**
1522    * @Assert\Callback({"callback"})
1523    */
1524   class MyClass
1525   {
1526       public function callback(ExecutionContextInterface $context)
1527       {
1528           // ...
1529       }
1530   }
1531   ```
1532
1533   After (Annotations):
1534
1535   ```php
1536   use Symfony\Component\Validator\Constraints as Assert;
1537   use Symfony\Component\Validator\ExecutionContextInterface;
1538
1539   class MyClass
1540   {
1541       /**
1542        * @Assert\Callback
1543        */
1544       public function callback(ExecutionContextInterface $context)
1545       {
1546           // ...
1547       }
1548   }
1549   ```
1550
1551 * The interface `ValidatorInterface` was replaced by the more powerful
1552   interface `Validator\ValidatorInterface`. The signature of the `validate()`
1553   method is slightly different in that interface and accepts a value, zero
1554   or more constraints and validation group. It replaces both
1555   `validate()` and `validateValue()` in the previous interface.
1556
1557   Before:
1558
1559   ```php
1560   $validator->validate($object, 'Strict');
1561
1562   $validator->validateValue($value, new NotNull());
1563   ```
1564
1565   After:
1566
1567   ```php
1568   $validator->validate($object, null, 'Strict');
1569
1570   $validator->validate($value, new NotNull());
1571   ```
1572
1573   Apart from this change, the new methods `startContext()` and `inContext()`
1574   were added. The first of them allows to run multiple validations in the
1575   same context and aggregate their violations:
1576
1577   ```php
1578   $violations = $validator->startContext()
1579       ->atPath('firstName')->validate($firstName, new NotNull())
1580       ->atPath('age')->validate($age, new Type('integer'))
1581       ->getViolations();
1582   ```
1583
1584   The second allows to run validation in an existing context. This is
1585   especially useful when calling the validator from within constraint
1586   validators:
1587
1588   ```php
1589   $validator->inContext($context)->validate($object);
1590   ```
1591
1592   Instead of a `Validator`, the validator builder now returns a
1593   `Validator\RecursiveValidator` instead.
1594
1595 * The interface `ValidationVisitorInterface` and its implementation
1596   `ValidationVisitor` were removed. The implementation of the visitor pattern
1597   was flawed. Fixing that implementation would have drastically slowed down
1598   the validator execution, so the visitor was removed completely instead.
1599
1600   Along with the visitor, the method `accept()` was removed from
1601   `MetadataInterface`.
1602
1603 * The interface `MetadataInterface` was moved to the `Mapping` namespace.
1604
1605   Before:
1606
1607   ```php
1608   use Symfony\Component\Validator\MetadataInterface;
1609   ```
1610
1611   After:
1612
1613   ```php
1614   use Symfony\Component\Validator\Mapping\MetadataInterface;
1615   ```
1616
1617   The methods `getCascadingStrategy()` and `getTraversalStrategy()` were
1618   added to the interface. The first method should return a bit mask of the
1619   constants in class `CascadingStrategy`. The second should return a bit
1620   mask of the constants in `TraversalStrategy`.
1621
1622   Example:
1623
1624   ```php
1625   use Symfony\Component\Validator\Mapping\TraversalStrategy;
1626
1627   public function getTraversalStrategy()
1628   {
1629       return TraversalStrategy::TRAVERSE;
1630   }
1631   ```
1632
1633 * The interface `PropertyMetadataInterface` was moved to the `Mapping`
1634   namespace.
1635
1636   Before:
1637
1638   ```php
1639   use Symfony\Component\Validator\PropertyMetadataInterface;
1640   ```
1641
1642   After:
1643
1644   ```php
1645   use Symfony\Component\Validator\Mapping\PropertyMetadataInterface;
1646   ```
1647
1648 * The interface `PropertyMetadataContainerInterface` was moved to the `Mapping`
1649   namespace and renamed to `ClassMetadataInterface`.
1650
1651   Before:
1652
1653   ```php
1654   use Symfony\Component\Validator\PropertyMetadataContainerInterface;
1655   ```
1656
1657   After:
1658
1659   ```php
1660   use Symfony\Component\Validator\Mapping\ClassMetadataInterface;
1661   ```
1662
1663   The interface now contains four additional methods:
1664
1665    * `getConstrainedProperties()`
1666    * `hasGroupSequence()`
1667    * `getGroupSequence()`
1668    * `isGroupSequenceProvider()`
1669
1670   See the inline documentation of these methods for more information.
1671
1672 * The interface `ClassBasedInterface` was removed. You should use
1673   `Mapping\ClassMetadataInterface` instead:
1674
1675   Before:
1676
1677   ```php
1678   use Symfony\Component\Validator\ClassBasedInterface;
1679
1680   class MyClassMetadata implements ClassBasedInterface
1681   {
1682       // ...
1683   }
1684   ```
1685
1686   After:
1687
1688   ```php
1689   use Symfony\Component\Validator\Mapping\ClassMetadataInterface;
1690
1691   class MyClassMetadata implements ClassMetadataInterface
1692   {
1693       // ...
1694   }
1695   ```
1696
1697 * The class `ElementMetadata` was renamed to `GenericMetadata`.
1698
1699   Before:
1700
1701   ```php
1702   use Symfony\Component\Validator\Mapping\ElementMetadata;
1703
1704   class MyMetadata extends ElementMetadata
1705   {
1706   }
1707   ```
1708
1709   After:
1710
1711   ```php
1712   use Symfony\Component\Validator\Mapping\GenericMetadata;
1713
1714   class MyMetadata extends GenericMetadata
1715   {
1716   }
1717   ```
1718
1719 * The interface `ExecutionContextInterface` and its implementation
1720   `ExecutionContext` were moved to the `Context` namespace.
1721
1722   Before:
1723
1724   ```php
1725   use Symfony\Component\Validator\ExecutionContextInterface;
1726   ```
1727
1728   After:
1729
1730   ```php
1731   use Symfony\Component\Validator\Context\ExecutionContextInterface;
1732   ```
1733
1734   The interface now contains the following additional methods:
1735
1736    * `getValidator()`
1737    * `getObject()`
1738    * `setNode()`
1739    * `setGroup()`
1740    * `markGroupAsValidated()`
1741    * `isGroupValidated()`
1742    * `markConstraintAsValidated()`
1743    * `isConstraintValidated()`
1744
1745   See the inline documentation of these methods for more information.
1746
1747   The method `addViolationAt()` was removed. You should use `buildViolation()`
1748   instead.
1749
1750   Before:
1751
1752   ```php
1753   $context->addViolationAt('property', 'The value {{ value }} is invalid.', array(
1754       '{{ value }}' => $invalidValue,
1755   ));
1756   ```
1757
1758   After:
1759
1760   ```php
1761   $context->buildViolation('The value {{ value }} is invalid.')
1762       ->atPath('property')
1763       ->setParameter('{{ value }}', $invalidValue)
1764       ->addViolation();
1765   ```
1766
1767   The methods `validate()` and `validateValue()` were removed. You should use
1768   `getValidator()` together with `inContext()` instead.
1769
1770   Before:
1771
1772   ```php
1773   $context->validate($object);
1774   ```
1775
1776   After:
1777
1778   ```php
1779   $context->getValidator()
1780       ->inContext($context)
1781       ->validate($object);
1782   ```
1783
1784   The parameters `$invalidValue`, `$plural` and `$code` were removed from
1785   `addViolation()`. You should use `buildViolation()` instead. See above for
1786   an example.
1787
1788   The method `getMetadataFactory()` was removed. You can use `getValidator()`
1789   instead and use the methods `getMetadataFor()` or `hasMetadataFor()` on the
1790   validator instance.
1791
1792   Before:
1793
1794   ```php
1795   $metadata = $context->getMetadataFactory()->getMetadataFor($myClass);
1796   ```
1797
1798   After:
1799
1800   ```php
1801   $metadata = $context->getValidator()->getMetadataFor($myClass);
1802   ```
1803
1804 * The interface `GlobalExecutionContextInterface` was removed. Most of the
1805   information provided by that interface can be queried from
1806   `Context\ExecutionContextInterface` instead.
1807
1808 * The interface `MetadataFactoryInterface` was moved to the `Mapping\Factory`
1809   namespace along with its implementations `BlackholeMetadataFactory` and
1810   `ClassMetadataFactory`. These classes were furthermore renamed to
1811   `BlackHoleMetadataFactory` and `LazyLoadingMetadataFactory`.
1812
1813   Before:
1814
1815   ```php
1816   use Symfony\Component\Validator\Mapping\ClassMetadataFactory;
1817
1818   $factory = new ClassMetadataFactory($loader);
1819   ```
1820
1821   After:
1822
1823   ```php
1824   use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory;
1825
1826   $factory = new LazyLoadingMetadataFactory($loader);
1827   ```
1828
1829 * The option `$deep` was removed from the constraint `Valid`. When traversing
1830   arrays, nested arrays are always traversed (same behavior as before). When
1831   traversing nested objects, their traversal strategy is used.
1832
1833 * The method `ValidatorBuilder::setPropertyAccessor()` was removed. The
1834   validator now functions without a property accessor.
1835
1836 * The methods `getMessageParameters()` and `getMessagePluralization()` in
1837   `ConstraintViolation` were renamed to `getParameters()` and `getPlural()`.
1838
1839   Before:
1840
1841   ```php
1842   $parameters = $violation->getMessageParameters();
1843   $plural = $violation->getMessagePluralization();
1844   ```
1845
1846   After:
1847
1848   ```php
1849   $parameters = $violation->getParameters();
1850   $plural = $violation->getPlural();
1851   ```
1852
1853 * The class `Symfony\Component\Validator\DefaultTranslator` was removed. You
1854   should use `Symfony\Component\Translation\IdentityTranslator` instead.
1855
1856   Before:
1857
1858   ```php
1859   $translator = new \Symfony\Component\Validator\DefaultTranslator();
1860   ```
1861
1862   After:
1863
1864   ```php
1865   $translator = new \Symfony\Component\Translation\IdentityTranslator();
1866   $translator->setLocale('en');
1867   ```
1868
1869### Yaml
1870
1871 * Using a colon in an unquoted mapping value leads to a `ParseException`.
1872 * Starting an unquoted string with `@`, `` ` ``, `|`, or `>` leads to a `ParseException`.
1873 * When surrounding strings with double-quotes, you must now escape `\` characters. Not
1874   escaping those characters (when surrounded by double-quotes) leads to a `ParseException`.
1875
1876   Before:
1877
1878   ```yml
1879   class: "Foo\Var"
1880   ```
1881
1882   After:
1883
1884   ```yml
1885   class: "Foo\\Var"
1886   ```
1887
1888
1889 * The ability to pass file names to `Yaml::parse()` has been removed.
1890
1891   Before:
1892
1893   ```php
1894   Yaml::parse($fileName);
1895   ```
1896
1897   After:
1898
1899   ```php
1900   Yaml::parse(file_get_contents($fileName));
1901   ```
1902
1903### WebProfiler
1904
1905 * The `profiler:import` and `profiler:export` commands have been removed.
1906
1907 * All the profiler storages different than `FileProfilerStorage` have been
1908   removed. The removed classes are:
1909
1910    - `Symfony\Component\HttpKernel\Profiler\BaseMemcacheProfilerStorage`
1911    - `Symfony\Component\HttpKernel\Profiler\MemcachedProfilerStorage`
1912    - `Symfony\Component\HttpKernel\Profiler\MemcacheProfilerStorage`
1913    - `Symfony\Component\HttpKernel\Profiler\MongoDbProfilerStorage`
1914    - `Symfony\Component\HttpKernel\Profiler\MysqlProfilerStorage`
1915    - `Symfony\Component\HttpKernel\Profiler\PdoProfilerStorage`
1916    - `Symfony\Component\HttpKernel\Profiler\RedisProfilerStorage`
1917    - `Symfony\Component\HttpKernel\Profiler\SqliteProfilerStorage`
1918
1919### Process
1920
1921 * `Process::setStdin()` and `Process::getStdin()` have been removed. Use
1922   `Process::setInput()` and `Process::getInput()` that works the same way.
1923 * `Process::setInput()` and `ProcessBuilder::setInput()` do not accept non-scalar types.
1924
1925### Monolog Bridge
1926
1927 * `Symfony\Bridge\Monolog\Logger::emerg()` was removed. Use `emergency()` which is PSR-3 compatible.
1928 * `Symfony\Bridge\Monolog\Logger::crit()` was removed. Use `critical()` which is PSR-3 compatible.
1929 * `Symfony\Bridge\Monolog\Logger::err()` was removed. Use `error()` which is PSR-3 compatible.
1930 * `Symfony\Bridge\Monolog\Logger::warn()` was removed. Use `warning()` which is PSR-3 compatible.
1931
1932### Swiftmailer Bridge
1933
1934 * `Symfony\Bridge\Swiftmailer\DataCollector\MessageDataCollector` was removed. Use the `Symfony\Bundle\SwiftmailerBundle\DataCollector\MessageDataCollector` class instead.
1935
1936### HttpFoundation
1937
1938 * The precedence of parameters returned from `Request::get()` changed from "GET, PATH, BODY" to "PATH, GET, BODY"
1939
1940 * `Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface` no longer implements the `IteratorAggregate` interface. Use the `all()` method instead of iterating over the flash bag.
1941
1942 * Removed the feature that allowed finding deep items in `ParameterBag::get()`.
1943   This may affect you when getting parameters from the `Request` class:
1944
1945   Before:
1946
1947   ```php
1948   $request->query->get('foo[bar]', null, true);
1949   ```
1950
1951   After:
1952
1953   ```php
1954   $request->query->get('foo')['bar'];
1955   ```
1956### Monolog Bridge
1957
1958 * `Symfony\Bridge\Monolog\Logger::emerg()` was removed. Use `emergency()` which is PSR-3 compatible.
1959 * `Symfony\Bridge\Monolog\Logger::crit()` was removed. Use `critical()` which is PSR-3 compatible.
1960 * `Symfony\Bridge\Monolog\Logger::err()` was removed. Use `error()` which is PSR-3 compatible.
1961 * `Symfony\Bridge\Monolog\Logger::warn()` was removed. Use `warning()` which is PSR-3 compatible.
1962