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