Symfony 5.2

9a22d09f92d50fa3d2a16766d0ba52f8?s=47 Fabien Potencier
September 23, 2020

Symfony 5.2

What's new in Symfony 5.2

9a22d09f92d50fa3d2a16766d0ba52f8?s=128

Fabien Potencier

September 23, 2020
Tweet

Transcript

  1. Symfony 5.2 Fabien Potencier @fabpot Icons made by Eucalyp from

    www.flaticon.com
  2. Console 240M downloads ❤

  3. Console Colors True color support via Hex CSS colors https://github.com/symfony/symfony/pull/36802

    $color = new Color('black', 'white'); echo $color->apply("foo"); $color = new Color('#000000', '#ffffff');
  4. private function rainbowColor(): Color { ++$this->color; if (256 === $this->color)

    { $this->color = 1; } $h = (int) ($this->color / 43); $f = (int) ($this->color - 43 * $h); $t = (int) ($f * 255 / 43); $q = 255 - $t; if ($h == 0) { return new Color('', sprintf('#FF%02x00', $t)); } elseif ($h == 1) { return new Color('', sprintf('#%02xFF00', $q)); } elseif ($h == 2) { return new Color('', sprintf('#00FF%02x', $t)); } elseif ($h == 3) { return new Color('', sprintf('#00%02xFF', $q)); } elseif ($h == 4) { return new Color('', sprintf('#%02x00FF', $t)); } elseif ($h == 5) { return new Color('', sprintf('#FF00%02x', $q)); } } Console Rainbows https://github.com/symfony/symfony/pull/36802 $output->write($this->rainbowColor()->apply(' '));
  5. https://symfony.com/blog/new-in-symfony-5-1-cursor-control namespace App\Command; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Cursor; use Symfony\Component\Console\Input\InputInterface; use

    Symfony\Component\Console\Output\OutputInterface; class SomeCommand extends Command { protected static $defaultName = 'app:some-command'; protected function execute(InputInterface $input, OutputInterface $output) { // ... $cursor = new Cursor($output); // argument for left/right is "number of columns" (1 by default) // argument for top/bottom is "number of rows" (1 by default) $cursor->moveUp(2)->moveRight(); $cursor->moveDown(); // move to an arbitrary (column, row) position $cursor->moveToPosition(7, 15); // you can show/hide the cursor, save/restore its position, etc. $cursor->savePosition()->hide(); } }
  6. Snake a Symfony Console Game https://github.com/dbu/snake-bundle

  7. Default Command vs Single Command Applications #!/usr/bin/env php <?php use

    Symfony\Component\Console\SingleCommandApplication; require __DIR__.'/vendor/autoload.php'; (new SingleCommandApplication()) ->setCode( function (InputInterface $input, OutputInterface $output) { // add here the code of your console command... } ) ->run(); #!/usr/bin/env php <?php use Dbu\SnakeBundle\Command\SnakeCommand; use Symfony\Component\Console\Application; require __DIR__.'/vendor/autoload.php'; $app = new Application(); $app->add(new SnakeCommand()); $app->setDefaultCommand('game:snake'); $app->run(); 5.1
  8. https://github.com/fabpot/snake-bundle/tree/rainbow-time

  9. Console Signals $game = new Game(80, 24); $app = new

    Application(); $app->add(new SnakeCommand($game)); $app->setDefaultCommand('game:snake'); $app->getSignalRegistry()->register(SIGUSR1, function ($signal) use ($game) { $game->cheat(); }); $app->run(); https://github.com/symfony/symfony/pull/33729 https://github.com/symfony/symfony/pull/37827 pkill -USR1 -f "php ./snake" https://github.com/fabpot/snake-bundle/tree/rainbow-time
  10. Translation Created 10 years ago ❤

  11. $invitation = '{organizer_gender, select, female {{organizer_name} has invited you for

    her party!} male {{organizer_name} has invited you for his party!} other {{organizer_name} have invited you for their party!} }'; // prints "Ryan has invited you for his party!" echo $translator->trans($invitation, [ 'organizer_name' => 'Ryan', 'organizer_gender' => 'male', ]); Translation: Standard ICU message format https://github.com/symfony/symfony/pull/37371
  12. Translation: Pseudo localization translator https://github.com/symfony/symfony/pull/36016

  13. $message = new Translatable('Symfony is great!'); $message = t('Symfony is

    great!'); Translatable::trans($translator, $message); Translation: Translatable objects https://github.com/symfony/symfony/pull/37670
  14. Form Mapping data using callback functions https://github.com/symfony/symfony/pull/37968 $builder->add('name', TextType::class, [

    'getter' => fn(Person $person, FormInterface $form): string => $person->firstName().' '.$person->lastName(); 'setter' => fn(Person &$person, ?string $name, FormInterface $form): void => $person->rename($name); ]);
  15. HttpClient

  16. HttpClient RetryableHttpClient use Symfony\Component\HttpClient\RetryableHttpClient; $client = new RetryableHttpClient(HttpClient::create()); framework: http_client:

    retry_failed: # backoff_service: app.custom_backoff # decider_service: app.custom_decider http_codes: [429, 500] max_retries: 2 delay: 1000 multiplier: 3 max_delay: 500 https://github.com/symfony/symfony/pull/38182
  17. HttpClient EventSourceHttpClient https://github.com/symfony/symfony/pull/36692

  18. Experimental Components get better!

  19. Uid: Better framework integration https://symfony.com/components/Uid Support in Serializer (via a

    dedicated Normalizer) - Just works Uid Doctrine types and generators Help needed - https://github.com/symfony/symfony/issues/36102 Uid constraint and more 5.1
  20. Notifier: Still experimental We need your feedback!

  21. Notifier: Many new providers 5.2 all 5.1 + Esendex GoogleChat

    Infobip LinkedIn Mobyt Smsapi Zulip 5.1 all 5.0 + Firebase FreeMobile Mattermost OvhCloud RocketChat Sinch 5.0 Nexmo Slack Telegram Twilio
  22. Providers are now more widespread Notifier Esendex * Firebase FreeMobile

    GoogleChat * Infobip * LinkedIn * Mattermost Mobyt * Nexmo OvhCloud RocketChat Sinch Slack Smsapi * Telegram Twilio Zulip * Messenger AmazonSqs Amqp Beanstalkd * Doctrine Redis Mailer Amazon Google Mailchimp Mailgun Mailjet * Postmark Sendgrid to be continued...
  23. Mailer: Incremental improvements More semantic configuration framework: mailer: dsn: '%env(MAILER_DSN)%'

    headers: from: 'company@example.com' bcc: 'me@example.com' https://github.com/symfony/symfony/pull/36736
  24. { "htmlTemplate": "email.html.twig", "textTemplate": "email.txt.twig", "context": { "foo": "bar" },

    "text": null, "textCharset": null, "html": null, "htmlCharset": null, "attachments": [ { "body": "Some Text file", "name": "test.txt", "content-type": null, "inline": false } ], "headers": { "to": [ { "addresses": [ { "address": "you@example.com", "name": "" } ] } ] }, "body": null, "message": null } Mailer: Incremental improvements Better serialization, lightweight payload and no binaries https://github.com/symfony/symfony/pull/37847
  25. $dkimSigner = new DkimSigner($pk, 'example.com', 'sf'); $signedEmail = $dkimSigner->sign($email); Mailer:

    Incremental improvements DKIM support Switch from Swiftmailer https://github.com/symfony/symfony/pull/37165
  26. Less code More automation

  27. Skeleton code simplification public/index.php use App\Kernel; use Symfony\Component\Dotenv\Dotenv; use Symfony\Component\ErrorHandler\Debug;

    use Symfony\Component\HttpFoundation\Request; require dirname(__DIR__).'/vendor/autoload.php'; (new Dotenv())->bootEnv(dirname(__DIR__).'/.env'); if ($_SERVER['APP_DEBUG']) { umask(0000); Debug::enable(); } if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? false) { Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST); } if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? false) { Request::setTrustedHosts([$trustedHosts]); } $kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']); $request = Request::createFromGlobals(); $response = $kernel->handle($request); $response->send(); $kernel->terminate($request, $response); framework: trusted_proxies: '127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16' # or trusted_proxies: '%env(TRUSTED_PROXIES)%' # that's the defaults already trusted_headers: ['x-forwarded-all', '!x-forwarded-host', '!x-forwarded-prefix'] https://github.com/symfony/symfony/pull/37357
  28. Skeleton code simplification HTTP Cache in public/index.php framework: http_cache: true

    No more PHP to enable PHP HTTP caching ❤ https://github.com/symfony/symfony/pull/37351
  29. Upgrade your project composer sync-recipes --force

  30. New Components

  31. Semaphore Component A semaphore allows N processes to access a

    resource A lock allows only 1 process to access a resource https://github.com/symfony/symfony/pull/35780
  32. Lock Component Single Write / Multiple Readers $aliceLock = $factory->createLock('invoice');

    $bobLock = $factory->createLock('invoice'); $oscarLock = $factory->createLock('invoice'); $aliceLock->acquireRead(); // true $bobLock->acquireRead(); // true $oscarLock->acquire(); // false https://github.com/symfony/symfony/pull/37752
  33. RateLimiter Component use Symfony\Component\RateLimiter\Storage\InMemoryStorage; use Symfony\Component\RateLimiter\Limiter; $limiter = new Limiter([

    'id' => 'login', 'strategy' => 'token_bucket', // or 'fixed_window' 'limit' => 10, 'rate' => ['interval' => '15 minutes'], ], new InMemoryStorage()); // blocks until 1 token is free to use for this process $limiter->reserve(1)->wait(); // ... execute the code // only claims 1 token if it's free at this moment if ($limiter->consume(1)) { // ... execute the code } RateLimiter Lock ??? Cache https://github.com/symfony/symfony/pull/37546
  34. Security reinvented

  35. Security Authenticators 4 main ideas VerifyAuthenticatorCredentialsEvent LoginSuccessEvent LoginFailureEvent PUBLIC_ACCESS vs

    ROLE_ANONYMOUS
  36. Security Login Throttling RateLimiter Lock Login Throttling Cache Security Authenticators

    5.1 3.3 3.1 5.2 5.2 security: firewalls: default: # default limits to 5 login attempts per minute, # the number can be configured via "max_attempts" login_throttling: ~ # define your own RateLimiter login_throttling: limiter: login https://github.com/symfony/symfony/pull/38204
  37. Security Authenticators unlock a lot of features Magic login link

    authentication https://github.com/symfony/symfony/pull/38177 2fa authentication https://github.com/scheb/2fa Help needed - https://github.com/symfony/symfony/issues/30914 Sudo mode and more
  38. Security Bootstrap a new project the fast way $ symfony

    new --version=next demo $ composer req maker profiler orm validator form security $ vi docker-compose.yml $ docker-compose up -d $ symfony server:start -d $ symfony open:local version: '3' services: database: image: postgres:12-alpine environment: POSTGRES_USER: main POSTGRES_PASSWORD: main POSTGRES_DB: main ports: [5432] mailer: image: schickling/mailcatcher ports: [1025, 1080]
  39. The name of the security user class (e.g. User) [User]:

    > Do you want to store user data in the database (via Doctrine)? (yes/no) [yes]: > Enter a property name that will be the unique "display" name for the user (e.g. email, username, uuid) [email]: > Will this app need to hash/check user passwords? Choose No if passwords are not needed or will be checked/hashed by some other system (e.g. a single sign-on server). Does this app need to hash/check user passwords? (yes/no) [yes]: > $ symfony console make:user
  40. What style of authentication do you want? [Empty authenticator]: [0]

    Empty authenticator [1] Login form authenticator > 1 The class name of the authenticator to create (e.g. AppCustomAuthenticator): > AppAuthenticator Choose a name for the controller class (e.g. SecurityController) [SecurityController]: > Do you want to generate a '/logout' URL? (yes/no) [yes]: > $ symfony console make:auth
  41. Creating a registration form for App\Entity\User Do you want to

    add a @UniqueEntity validation annotation on your User class to make sure duplicate accounts aren't created? (yes/no) [yes]: > Do you want to send an email to verify the user's email address after registration? (yes/no) [yes]: > [WARNING] We're missing some important components. Don't forget to install these after you're finished. composer require symfonycasts/verify-email-bundle symfony/mailer What email address will be used to send registration confirmations? e.g. mailer@your-domain.com: > demo@example.com What "name" should be associated with that email address? e.g. "Acme Mail Bot": > Demo Bot Do you want to automatically authenticate the user after registration? (yes/no) [yes]: > $ symfony console make:registration-form
  42. --- a/src/Security/AppAuthenticator.php +++ b/src/Security/AppAuthenticator.php @@ -96,8 +96,7 @@ class AppAuthenticator

    extends AbstractFormLoginAuthenticator implements Passwor return new RedirectResponse($targetPath); } - // For example : return new RedirectResponse($this->urlGenerator->generate('some_route')); - throw new \Exception('TODO: provide a valid redirect inside '.__FILE__); + return new RedirectResponse($this->urlGenerator->generate('app_login')); } protected function getLoginUrl() $ symfony console make:registration-form
  43. Security Bootstrap a new project the fast way $ symfony

    make:migration $ symfony console doctrine:migrations:migrate -n
  44. https://127.0.0.1:8000/register $ symfony open:local:webmail

  45. https://127.0.0.1:8000/logout https://127.0.0.1:8000/login

  46. 2FA / MFA https://github.com/scheb/2fa

  47. &

  48. PHP 8 Attributes use Symfony\Component\Routing\Attribute\Route; class ActionPathController { #[Route('/{name}', name:

    'hello')] public function action() { } } class AutowireSetter { #[Required] public function setFoo(Foo $foo): void { } } https://github.com/symfony/symfony/pull/37545 https://github.com/symfony/symfony/pull/37474
  49. PHP 8 Attributes We need your help https://github.com/symfony/symfony/issues/38096 https://github.com/symfony/symfony/pull/38162 Add

    support for Constraints Think of new possibilities Replace SensioFrameworkExtraBundle public function searchAction( #[RequestQuery] string $q, #[RequestQuery] int $page = 1 ) {
  50. Speed improvements

  51. Cache + Messenger = framework: cache: pools: test.cache: early_expiration_message_bus: messenger.default_bus

    messenger: routing: 'Symfony\Component\Cache\Messenger\EarlyExpirationMessage': amqp https://github.com/symfony/symfony/pull/30572
  52. PHP 7.4 preloading opcache.preload=/app/src/.preload.php

  53. Some fun again French Inflector use Symfony\Component\String\Inflector\FrenchInflector; $inflector = new

    FrenchInflector(); $result = $inflector->singularize('dents'); // ['dent'] $result = $inflector->singularize('souris'); // ['souris'] $result = $inflector->singularize('messieurs'); // ['monsieur'] $result = $inflector->pluralize('cinquante'); // ['cinquante'] $result = $inflector->pluralize('pou'); // ['poux'] $result = $inflector->pluralize('cheval'); // ['chevaux'] https://github.com/symfony/symfony/pull/36929
  54. https://symfony.com/sponsor Support Symfony Thank you!