Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Get ready for Symfony 4

Get ready for Symfony 4

B50a40d1c576ef0aa065cbc5d4d6dec9?s=128

Christian Flothmann

February 23, 2017
Tweet

Transcript

  1. SensioLabs Get ready for Symfony 4

  2. Christian Flothmann Symfony Core Team & Documentation Team work at

    SensioLabs Germany github.com/xabbuh @xabbuh
  3. The Symfony Release Cycle

  4. None
  5. • one patch release a month • minor releases twice

    a year • new major releases every two years • N.4 at the same time as (N+1).0 • N.4 is an LTS release The Symfony Release Cycle http://symfony.com/roadmap
  6. Symfony 3.3

  7. Workflow

  8. • new Twig function: workflow_has_place() • new Event: workflow.entered Workflow

  9. Dotenv

  10. • new component • reads .env files • makes them

    available through getenv(), $_SERVER, and $_ENV Dotenv
  11. An example .env file # Database credentials DB_USER=root DB_PASS=pass #

    the DB password
  12. Loading a .env file $loader = require __DIR__.'/../app/autoload.php'; use Symfony\Component\Dotenv\Dotenv;

    if (file_exists(__DIR__.'/../.env')) { $dotenv = new Dotenv(); $dotenv->load(__DIR__.'/../.env'); } Debug::enable(); $kernel = new AppKernel('dev', true); $request = Request::createFromGlobals(); $response = $kernel->handle($request); $response->send(); $kernel->terminate($request, $response);
  13. Cache

  14. • compatible with PSR-16 o simple caching Layer o support

    to convert PSR-16 caches to PSR-6 adapters and vice versa • Memcached Support Cache
  15. Cache – PSR-6 interface CacheItemInterface { public function getKey(); public

    function get(); public function isHit(); public function set($value); public function expiresAt($expiration); public function expiresAfter($time); }
  16. Cache – PSR-6 interface CacheItemPoolInterface { public function getItem($key); public

    function getItems(array $keys = array()); public function hasItem($key); public function clear(); public function deleteItem($key); public function deleteItems(array $keys); public function save(CacheItemInterface $item); public function saveDeferred(CacheItemInterface $item); public function commit(); }
  17. Cache – PSR-16 interface CacheInterface { public function get($key, $default

    = null); public function set($key, $value, $ttl = null); public function delete($key); public function clear(); public function getMultiple($keys, $default = null); public function setMultiple($values, $ttl = null); public function deleteMultiple($keys); public function has($key); }
  18. Cache – Using PSR-16 Caches use Symfony\Component\Cache\Simple\FilesystemCache; $cache = new

    FilesystemCache(); $cache->set('stats.num_products', 4711, 3600); if (!$cache->has('stats.num_products')) { // ... item does not exists in the cache } $numProducts = $cache->get( 'stats.num_products‘, 100 ); $cache->delete('stats.num_products'); $cache->clear();
  19. Cache – PSR-16 to PSR-6 use Symfony\Component\Cache\Simple\FilesystemCache; use Symfony\Component\Cache\Adapter\SimpleCacheAdapter; $psr16Cache

    = new FilesystemCache(); $psr6Cache = new SimpleCacheAdapter($psr16Cache);
  20. Cache – PSR-6 to PSR-16 use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Component\Cache\Simple\Psr6Cache; $psr6Cache

    = new FilesystemAdapter(); $psr16Cache = new Psr6Cache($psr6Cache);
  21. DependencyInjection

  22. Importing config files in Symfony 3.2 imports: - { resource:

    parameters.yml } - { resource: security.yml } - { resource: services.yml } - { resource: admin/ }
  23. Importing config files using glob patterns imports: - { resource:

    "*.yml" } - { resource: "common/**/*.xml" } - { resource: "/etc/myapp/*.{yml,xml}" } - { resource: "bundles/*/{xml,yaml}/services.{yml,xml}" } Support for double star (**) in glob patterns is part of the Finder component in 3.3.
  24. • class is optional, falls back to id • support

    for default values per file • inheritance of tags from parent definition Configuration improvements
  25. Verbose config before Symfony 3.3 services: app.voter: abstract: true autowire:

    true public: false app.category_voter: class: AppBundle\Security\CategoryVoter parent: app.voter tags: [ { name: security.voter } ] app.comment_voter: class: AppBundle\Security\CommentVoter parent: app.voter tags: [ { name: security.voter } ] app.post_voter: class: AppBundle\Security\PostVoter parent: app.voter tags: [ { name: security.voter } ]
  26. Shortened config with Symfony 3.3 services: _defaults: autowire: true public:

    false tags: - name: security.voter AppBundle\Security\CategoryVoter: ~ AppBundle\Security\CommentVoter: ~ AppBundle\Security\PostVoter: ~
  27. Inheriting tags in Symfony 3.3 services: _defaults: autowire: true public:

    false inherit_tags: true app.voter: abstract: true tags: [ { name: security.voter } ] AppBundle\Security\CategoryVoter: parent: app.voter AppBundle\Security\CommentVoter: parent: app.voter AppBundle\Security\PostVoter: parent: app.voter AppBundle\Security\UserProvider: inherit_tags: false
  28. Factory methods before Symfony 3.3 services: app.mailer: class: AppBundle\Mailer factory:

    - AppBundle\Mailer - getDefaultMailer
  29. Omitting the factory method services: app.mailer: class: AppBundle\Mailer factory: -

    ~ - getDefaultMailer
  30. Experimental Features

  31. None
  32. DependencyInjection

  33. Simplifying the voter example services: _defaults: autowire: true public: false

    tags: - name: security.voter AppBundle\Security\CategoryVoter: ~ AppBundle\Security\CommentVoter: ~ AppBundle\Security\PostVoter: ~
  34. Using PSR-4 based discovery # app/config/services.yml services: AppBundle\Security\: resource: ../../src/AppBundle/Security

    autowire: true public: false tags: - name: security.voter
  35. Getter injection abstract class NewsletterManager { abstract protected function getMailer():

    MailerInterface; protected function getLogger(): LoggerInterface { return new NullLogger(); } // ... }
  36. Getter injection services: app.newsletter_manager: class: AppBundle\Mail\NewsletterManager getters: getMailer: '@mailer' getLogger:

    '@logger'
  37. Getter autowiring services: app.newsletter_manager: class: AppBundle\Mail\NewsletterManager autowire: ['get*'] AppBundle\Mailer: ~

    MailerInterface: '@AppBundle\Mailer'
  38. Inheriting tags in Symfony 3.3 services: _defaults: autowire: true public:

    false inherit_tags: true app.voter: abstract: true tags: [ { name: security.voter } ] AppBundle\Security\CategoryVoter: parent: app.voter AppBundle\Security\CommentVoter: parent: app.voter AppBundle\Security\PostVoter: parent: app.voter AppBundle\Security\UserProvider: inherit_tags: false
  39. Interface based attribute configuration services: _defaults: autowire: true public: false

    _instanceof: Symfony\Component\Security\Core\Authorization\Voter\Voter: tags: [ { name: security.voter } ] AppBundle\Security\CategoryVoter: ~ AppBundle\Security\CommentVoter: ~ AppBundle\Security\PostVoter: ~ AppBundle\Security\UserProvider: ~
  40. Symfony 4.0

  41. ClassLoader

  42. • component is to be removed • use Composer instead

    • (or any other PSR-4 compatible autoloader package) ClassLoader
  43. DependencyInjection

  44. • service identifiers are case sensitive • invalid options (YAML

    format) lead to exceptions • private services are not accessible through Container::has() or Container::get(), inject them if needed DependencyInjection
  45. DefinitionDecorator is deprecated $mailer = $container->register('mailer', 'Mailer'); $mailer->setAbstract(true); $smtpMailer =

    new DefinitionDecorator('mailer'); $smtpMailer->setArguments([ 'username' => 'foo', 'password' => 'bar', ]); $container->setDefinition('mailer1', $smtpMailer);
  46. Use ChildDefinition instead $mailer = $container->register('mailer', 'Mailer'); $mailer->setAbstract(true); $smtpMailer =

    new ChildDefinition ('mailer'); $smtpMailer->setArguments([ 'username' => 'foo', 'password' => 'bar', ]); $container->setDefinition('mailer1', $smtpMailer);
  47. Form

  48. • choices_as_values option removed • part of BC layer of

    Symfony 2.7 • deprecated since Symfony 3.1 ChoiceType
  49. • dropped support to pass callables as strings to choice_value/choice_label

    ChoiceType
  50. Callable as string, before Symfony 4 public function buildForm( FormBuilderInterface

    $builder, array $options ) { $builder->add( 'categories', ChoiceType::class, [ 'choice_label' => 'strtolower', ] ); }
  51. Callables in Symfony 4 public function buildForm( FormBuilderInterface $builder, array

    $options ) { $builder->add( 'categories', ChoiceType::class, [ 'choice_label' => function ($choice) { return strtolower($choice); }, ] ); }
  52. • isValid() cannot be called for not submitted forms Form

  53. Before Symfony 4 $form = $this->createForm( UserType::class, $user ); $form->handleRequest($request);

    if ($form->isValid()) { // do something with // the submitted data }
  54. Symfony 4 $form = $this->createForm( UserType::class, $user ); $form->handleRequest($request); if

    ( $form->isSubmitted() && $form->isValid() ) { // do something with // the submitted data }
  55. HttpFoundation

  56. • lots of methods are final • don‘t override them

    in custom response classes Response
  57. • isMethodSafe() doesn‘t check for cacheable methods • HEAD and

    GET are cacheable • OPTIONS and TRACE are safe too Request
  58. Cacheable methods check before 4.0 if ( $request->isMethodSafe() ) {

    // true for GET, HEAD }
  59. Cacheable methods check with Symfony 4 if ( $request->isMethodCacheable() )

    { // true for GET, HEAD }
  60. Check for safe methods // note: true necessary only for

    // BC in Symfony 3.x if ( $request->isMethodSafe(true) ) { // true for GET, HEAD, // OPTIONS, and TRACE }
  61. Security

  62. • RoleInterface removed • use strings for roles • not

    recommend: extending the Role class o Role class likely to be removed too Security
  63. Validator

  64. • base class for validator tests located in Symfony\Component\Validator\Test (not

    Tests) AbstractConstraintValidatorTest
  65. strict option defaults to true /** * @Assert\Choice( * choices

    = { * "male", "female“ * }, * strict = true * ) */
  66. Yaml

  67. • mapping keys must be unique • colons separating keys

    and values need a following space • strings starting with % must be quoted Parser changes
  68. Valid YAML file before Symfony 4 foo: { bar:baz, a:

    b } foo: baz bar: %foobar
  69. Valid YAML file with Symfony 4 foo: { bar: baz,

    a: b } bar: '%foobar'
  70. • dropped boolean arguments of Yaml::parse() • dropped boolean arguments

    of Yaml::dump() • use flags instead API changes
  71. Parsing/dumping before Yaml::parse( '{ "foo": "bar", "foobar": "baz" }', true,

    true, true ); Yaml::dump( array('foo' => new A(), 'bar' => 1), 2, 4, true, true );
  72. Parsing/dumping with Symfony 4 Yaml::parse( '{ "foo": "bar", "foobar": "baz"

    }', Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE | Yaml::PARSE_OBJECT | Yaml::PARSE_OBJECT_FOR_MAP ); Yaml::dump( array('foo' => new A(), 'bar' => 1), 2, 4, Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE | Yaml::DUMP_OBJECT );
  73. SensioLabs Thank you!