Save 37% off PRO during our Black Friday Sale! »

What's New in Symfony 5.1?

What's New in Symfony 5.1?

3dd28ad260d202a12c2e93fc28fad5d7?s=128

Marco Petersen

May 19, 2020
Tweet

Transcript

  1. What's New in Symfony 5.1?

  2. ! Marco Petersen " Software Developer @ SensioLabs # @ocrampete16

  3. Symfony 5.1 Status • In development • Release: End of

    May 2020 • End of support: January 2021
  4. LTS vs Latest Release • Try and keep up with

    the latest release! • New features are added in minor releases. • Major version jumps (eg. 4.4 ➡ 5.0) only remove deprecated APIs.
  5. Deprecations

  6. Deprecation(s)

  7. The Inflector Component • converts between singular and plural forms

    in English • moved to the String component // before use Symfony\Component\Inflector\Inflector; Inflector::singularize('alumni'); // 'alumnus' Inflector::pluralize('person'); // ['persons', 'people'] // after use Symfony\Component\String\Inflector\EnglishInflector; $inflector = new EnglishInflector(); $result = $inflector->singularize('teeth'); // ['tooth'] $result = $inflector->pluralize('person'); // ['persons', 'people']
  8. namespace Symfony\Component\String\Inflector; interface InflectorInterface { // the returned values are

    arrays because in some cases, there // are multiple valid singulars/plurals for a given word public function singularize(string $plural): array; public function pluralize(string $singular): array; }
  9. What's New?

  10. Uid Component Contributed by Grégoire Pineau and Nicolas Grekas use

    Symfony\Component\Uid\Uuid; use Symfony\Component\Uid\Ulid; // generating a random UUID type 4 (all UUID types are supported) $uuid = Uuid::v4(); // generating a UUID Type 6 (which is not part of the standard, but it's // supported by the component because it's popular enough) $uuid = Uuid::v6(); // generating a ULID (there's only one type of them) $ulid = new Ulid();
  11. // checking if some UUID is null use Symfony\Component\Uid\NilUuid; if

    ($uuid instanceof NilUuid) { // ... } // comparing UUIDs $uuid1 = Uuid::v1(); $uuid4 = Uuid::v4(); $uuid1->equals($uuid4); // false // converting to different formats $ulid = Ulid::fromString('01E439TP9XJZ9RPFH3T1PYBCR8'); $ulid->toBinary(); // string(16) "..." (binary contents can't be printed) $ulid->toBase32(); // string(26) "01E439TP9XJZ9RPFH3T1PYBCR8" $ulid->toBase58(); // string(22) "1BKocMc5BnrVcuq2ti4Eqm" $ulid->toRfc4122(); // string(36) "0171069d-593d-97d3-8b3e-23d06de5b308"
  12. Async AWS Support Contributed by Jérémy Derussé and Tobias Nyholm

    • https://async-aws.com/ • an unofficial SDK for AWS • asynchronous by default (uses the Symfony HTTP Client) • Symfony 5.1 now uses it by default if it is installed: $ composer require async-aws/<package>
  13. New and Improved Integrations By various contributors • Lock: MongoDB

    integration • Cache: Couchbase adapter, SodiumMarshaller for encryption, LRU for ArrayCache • Mailer: improved Mailgun integration • Messenger: AWS SQS, PostgreSQL & improved Redis integration • Notifier: Mattermost & RocketChat (chat), Firebase (push), OVH Cloud & Sinch & Free Mobile (SMS)
  14. Service Container

  15. Support for typed properties in PropertyInfo Contributed by Kévin Dunglas

    use Symfony\Component\HttpFoundation\Request; class SomeClass { public int $id; protected string $name; private ?bool $logResult; public Request $request; // ... }
  16. $info = $propertyInfo->getTypes(SomeClass::class, 'logResult'); // $info = [ // class

    Symfony\Component\PropertyInfo\Type (6) { // private $builtinType => string(4) "bool" // private $nullable => bool(true) // private $class => NULL // private $collection => bool(false) // private $collectionKeyType => NULL // private $collectionValueType => NULL // } // ]
  17. Autowire public typed properties Contributed by Sébastien Morel use Twig\Environment;

    class SomeServiceClass { /** @required */ public Environment $twig; public function someMethod() { $this->twig->render('...'); // ... } }
  18. Simpler service decoration Contributed by Nicolas Grekas # config/services.yaml services:

    App\Mailer: ~ # Before App\SpecialMailer: decorates: App\Mailer arguments: ['@App\SpecialMailer.inner'] # After App\SpecialMailer: decorates: App\Mailer arguments: ['@.inner']
  19. Stack decorators Contributed by Nicolas Grekas services: # before App\Mailer\Mailer:

    ~ App\Mailer\RateLimitedMailer: decorates: App\Mailer\Mailer arguments: [20] # mails per second App\Mailer\LoggingMailer: decorates: App\Mailer\Mailer # after App\Mailer\Mailer: stack: - App\Mailer\LoggingMailer: ~ - App\Mailer\RateLimitedMailer: arguments: [20] - App\Mailer\Mailer: ~
  20. Abstract service arguments Contributed by Islam Israfilov services: # before

    Symfony\Bundle\MakerBundle\Generator: $rootNamespace: ~ # defined in MakerPass # after Symfony\Bundle\MakerBundle\Generator: $rootNamespace: !abstract defined in MakerPass
  21. Deprecate public services into private services Contributed by Thomas Calvet

    services: foo: # ... public: true tags: - { name: 'container.private', package: 'foo/bar', 'version': '1.2' } Since foo/bar 1.2: Accessing the "foo" service directly from the container is deprecated, use dependency injection instead.
  22. Routing

  23. Different hosts per locale Contributed by Olivier Dolbeau # config/routes/annotations.yaml

    controllers: resource: '../../src/Controller/' type: annotation host: fr: www.example.fr en: www.example.com
  24. Simpler Request Context Contributed by Benjamin Lévêque and Nicolas Grekas

    # Before parameters: router.request_context.scheme: 'https' router.request_context.host: 'example.org' router.request_context.base_url: 'my/path' # After framework: router: default_uri: 'https://example.org/my/path/'
  25. Route annotations priority Contributed by Nicolas Grekas /** * @Route("/{some_parameter}",

    name="route1") */ public function someMethod(): Response { // ... } /** * @Route("/foo", priority=10, name="route2") */ public function anotherMethod(): Response { // ... }
  26. Stateless Routes Contributed by Mathias Arlaud // src/Controller/MainController.php namespace App\Controller;

    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Routing\Annotation\Route; class MainController extends AbstractController { /** * @Route("/", name="homepage", stateless=true) */ public function homepage() { // ... } }
  27. Env vars in route conditions Contributed by Ahmed Tailouloute /**

    * @Route("/new-feature", condition="env('bool:IS_FEATURE_ENABLED') === true") */ public function __invoke() { // this route will only execute when the value of the // IS_FEATURE_ENABLED env var is TRUE }
  28. Validator

  29. Reusable constraint sets Contributed by Maxime Steinhausser use Symfony\Component\Validator\Constraints\Compound; /**

    * @Annotation */ class MatchesPasswordRequirements extends Compound { protected function getConstraints(array $options): array { return [ new NotBlank(), new Type('string'), new Length(['min' => 12]), new NotCompromisedPassword(), ]; } }
  30. namespace App\Dto; // ... use App\Validator\MatchesPasswordRequirements; class ChangePasswordDto { /**

    * @MatchesPasswordRequirements */ private $newPassword; // ... }
  31. /** * @var string * * @Assert\Sequentially({ * @Assert\Type("string"), *

    @Assert\Length(min="4"), * @Assert\Regex("[a-z]"), * @SomeCustomConstraintWithHeavyExternalCalls(), * }) */ public $someProperty;
  32. AtLeastOneOf validator Contributed by Przemysław Bogusz /** * @Assert\AtLeastOneOf({ *

    @Assert\Length(min=5), * @Assert\EqualTo("bar") * }) */ public $name = 'foo'; /** * @Assert\AtLeastOneOf({ * @Assert\All({@Assert\GreaterThanOrEqual(10)}), * @Assert\Count(20) * }) */ public $numbers = ['3', '5']; /** * @Assert\All({ * @Assert\AtLeastOneOf({ * @Assert\GreaterThanOrEqual(5), * @Assert\LessThanOrEqual(3) * }) * }) */ public $otherNumbers = ['4', '5'];
  33. Hostname Validator Contributed by Dmitrii Poddubnyi // src/Entity/ServerSettings.php namespace App\Entity;

    use Symfony\Component\Validator\Constraints as Assert; class ServerSettings { /** * @Assert\Hostname(message="The server name must be a valid hostname.") */ protected $name; }
  34. Security

  35. Simpler security attributes Contributed by Jules Pietri and Wouter De

    Jong // BEFORE $this->isGranted('IS_AUTHENTICATED_REMEMBERED') && !$this->isGranted('IS_AUTHENTICATED_FULLY'); $this->isGranted('IS_AUTHENTICATED_ANONYMOUSLY') && !$this->isGranted('IS_AUTHENTICATED_REMEMBERED') && !$this->isGranted('IS_AUTHENTICATED_FULLY'); $this->isGranted('ROLE_PREVIOUS_ADMIN'); // AFTER $this->isGranted('IS_REMEMBERED'); $this->isGranted('IS_ANONYMOUS'); $this->isGranted('IS_IMPERSONATOR');
  36. Access decision based on voter priority Contributed by Andreas Schempp

    # config/packages/security.yaml security: access_decision_manager: strategy: priority # ...
  37. Simpler logout customization Contributed by Wouter De Jong # config/services.yaml

    services: # ... App\EventListener\MyCustomLogoutListener: tags: - name: 'kernel.event_listener' event: 'Symfony\Component\Security\Http\Event\LogoutEvent' dispatcher: security.event_dispatcher.main
  38. "Microapplications"

  39. Improved Microkernel Contributed by Nicolas Grekas class MySymfonyApp extends Kernel

    { use MicroKernelTrait; protected function configureContainer(ContainerConfigurator $container): void { $container->services() ->load('App\\', '../src') ->set(Foo::class)->factory([$this, 'createFoo']); } public function createFoo(Bar $bar) { return new Foo($bar); } protected function configureRoutes(RoutingConfigurator $routes): void { $routes->add('home', '/')->controller([$this, 'helloAction']); } public function helloAction(Foo $foo) { return new Response('Hello '.get_class($foo)); } }
  40. $app = new MySymfonyApp('dev', true); $request = Request::createFromGlobals(); $response =

    $app->handle($request); $response->send(); $app->terminate($request, $response);
  41. Single command applications Contributed by Grégoire Pineau use Symfony\Component\Console\Input\InputArgument; use

    Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\SingleCommandApplication; (new SingleCommandApplication()) ->setName('My Super Command') ->setVersion('1.0.0') ->setHelp('This command allows you to...') ->addArgument('foo', InputArgument::OPTIONAL, 'The directory') ->addOption('bar', null, InputOption::VALUE_REQUIRED) ->setCode(function (InputInterface $input, OutputInterface $output) { // ... }) ->run();
  42. Miscellaneous Changes

  43. Configurable PHP Preloading Contributed by Nicolas Grekas services: twig: class:

    Twig\Environment # ... tags: - { name: 'container.preload', class: 'Twig\Cache\FilesystemCache' } - { name: 'container.preload', class: 'Twig\Extension\CoreExtension' } - { name: 'container.preload', class: 'Twig\Extension\EscaperExtension' } - { name: 'container.preload', class: 'Twig\Extension\OptimizerExtension' } # ...
  44. Simpler login in tests Contributed by Wouter De Jong public

    function testVisitingWhileLoggedIn() { $client = static::createClient(); // get or create the user somehow (e.g. creating some users only // for tests while loading the test fixtures) $userRepository = static::$container->get(UserRepository::class); $testUser = $userRepository->findOneByEmail('jane.doe@example.com'); $client->loginUser($testUser); // user is now logged in, so you can test protected resources $client->request('GET', '/profile'); $this->assertResponseIsSuccessful(); $this->assertSelectorTextContains('h1', 'Hello Username!'); }
  45. Thanks for watching! Thanks to all of you who make

    Symfony . $kernel->terminate($request, $response);
  46. None