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

Get ready for Symfony 4

Get ready for Symfony 4

Christian Flothmann

February 23, 2017
Tweet

More Decks by Christian Flothmann

Other Decks in Programming

Transcript

  1. SensioLabs
    Get ready for
    Symfony 4

    View full-size slide

  2. Christian Flothmann
    Symfony Core Team &
    Documentation Team
    work at SensioLabs Germany
    github.com/xabbuh
    @xabbuh

    View full-size slide

  3. The Symfony
    Release Cycle

    View full-size slide

  4. • 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

    View full-size slide

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

    View full-size slide

  6. • new component
    • reads .env files
    • makes them available through getenv(),
    $_SERVER, and $_ENV
    Dotenv

    View full-size slide

  7. An example .env file
    # Database credentials
    DB_USER=root
    DB_PASS=pass # the DB password

    View full-size slide

  8. 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);

    View full-size slide

  9. • 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

    View full-size slide

  10. 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);
    }

    View full-size slide

  11. 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();
    }

    View full-size slide

  12. 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);
    }

    View full-size slide

  13. 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();

    View full-size slide

  14. 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);

    View full-size slide

  15. 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);

    View full-size slide

  16. DependencyInjection

    View full-size slide

  17. Importing config files in Symfony 3.2
    imports:
    - { resource: parameters.yml }
    - { resource: security.yml }
    - { resource: services.yml }
    - { resource: admin/ }

    View full-size slide

  18. 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.

    View full-size slide

  19. • class is optional, falls back to id
    • support for default values per file
    • inheritance of tags from parent
    definition
    Configuration improvements

    View full-size slide

  20. 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 } ]

    View full-size slide

  21. 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: ~

    View full-size slide

  22. 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

    View full-size slide

  23. Factory methods before Symfony 3.3
    services:
    app.mailer:
    class: AppBundle\Mailer
    factory:
    - AppBundle\Mailer
    - getDefaultMailer

    View full-size slide

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

    View full-size slide

  25. Experimental
    Features

    View full-size slide

  26. DependencyInjection

    View full-size slide

  27. Simplifying the voter example
    services:
    _defaults:
    autowire: true
    public: false
    tags:
    - name: security.voter
    AppBundle\Security\CategoryVoter: ~
    AppBundle\Security\CommentVoter: ~
    AppBundle\Security\PostVoter: ~

    View full-size slide

  28. Using PSR-4 based discovery
    # app/config/services.yml
    services:
    AppBundle\Security\:
    resource: ../../src/AppBundle/Security
    autowire: true
    public: false
    tags:
    - name: security.voter

    View full-size slide

  29. Getter injection
    abstract class NewsletterManager
    {
    abstract protected function getMailer(): MailerInterface;
    protected function getLogger(): LoggerInterface
    {
    return new NullLogger();
    }
    // ...
    }

    View full-size slide

  30. Getter injection
    services:
    app.newsletter_manager:
    class: AppBundle\Mail\NewsletterManager
    getters:
    getMailer: '@mailer'
    getLogger: '@logger'

    View full-size slide

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

    View full-size slide

  32. 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

    View full-size slide

  33. 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: ~

    View full-size slide

  34. • component is to be removed
    • use Composer instead
    • (or any other PSR-4 compatible
    autoloader package)
    ClassLoader

    View full-size slide

  35. DependencyInjection

    View full-size slide

  36. • 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

    View full-size slide

  37. 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);

    View full-size slide

  38. 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);

    View full-size slide

  39. • choices_as_values option removed
    • part of BC layer of Symfony 2.7
    • deprecated since Symfony 3.1
    ChoiceType

    View full-size slide

  40. • dropped support to pass callables as
    strings to choice_value/choice_label
    ChoiceType

    View full-size slide

  41. Callable as string, before Symfony 4
    public function buildForm(
    FormBuilderInterface $builder,
    array $options
    ) {
    $builder->add(
    'categories',
    ChoiceType::class,
    [
    'choice_label' => 'strtolower',
    ]
    );
    }

    View full-size slide

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

    View full-size slide

  43. • isValid() cannot be called for not
    submitted forms
    Form

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  46. HttpFoundation

    View full-size slide

  47. • lots of methods are final
    • don‘t override them in custom response
    classes
    Response

    View full-size slide

  48. • isMethodSafe() doesn‘t check for
    cacheable methods
    • HEAD and GET are cacheable
    • OPTIONS and TRACE are safe too
    Request

    View full-size slide

  49. Cacheable methods check before 4.0
    if (
    $request->isMethodSafe()
    ) {
    // true for GET, HEAD
    }

    View full-size slide

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

    View full-size slide

  51. 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
    }

    View full-size slide

  52. • RoleInterface removed
    • use strings for roles
    • not recommend: extending the Role
    class
    o Role class likely to be removed too
    Security

    View full-size slide

  53. • base class for validator tests located in
    Symfony\Component\Validator\Test (not
    Tests)
    AbstractConstraintValidatorTest

    View full-size slide

  54. strict option defaults to true
    /**
    * @Assert\Choice(
    * choices = {
    * "male", "female“
    * },
    * strict = true
    * )
    */

    View full-size slide

  55. • mapping keys must be unique
    • colons separating keys and values need a
    following space
    • strings starting with % must be quoted
    Parser changes

    View full-size slide

  56. Valid YAML file before Symfony 4
    foo: { bar:baz, a: b }
    foo: baz
    bar: %foobar

    View full-size slide

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

    View full-size slide

  58. • dropped boolean arguments of
    Yaml::parse()
    • dropped boolean arguments of
    Yaml::dump()
    • use flags instead
    API changes

    View full-size slide

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

    View full-size slide

  60. 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
    );

    View full-size slide

  61. SensioLabs
    Thank you!

    View full-size slide