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

2 new Symfony components: HttpClient and MIME

2 new Symfony components: HttpClient and MIME

Fabien Potencier

March 01, 2019
Tweet

More Decks by Fabien Potencier

Other Decks in Technology

Transcript

  1. Back to the basics...
    Fabien Potencier
    @fabpot

    View Slide

  2. Process > proc_open()
    VarDumper > var_dump()
    VarExporter > var_export()
    Finder > *Iterator
    HttpFoundation > $_GET/$_POST
    HttpKernel > echo
    What's next?

    View Slide

  3. file_get_contents()
    no dependencies

    View Slide

  4. 3) Symfony HTTPClient
    Do HTTP requests, the powerful way
    Fabien Potencier
    @fabpot

    View Slide

  5. View Slide

  6. View Slide

  7. View Slide

  8. View Slide

  9. View Slide

  10. View Slide

  11. View Slide

  12. View Slide

  13. View Slide

  14. View Slide

  15. View Slide

  16. Great DX - Great Perf - Great Design
    (auto) proxy configuration
    DNS cache pre-population
    1st class error handling
    auto-gzip compression
    timeout management
    public key pinning
    progress callback
    extended info
    request abort
    HTTP/2-push
    IDN support
    Psr18Client
    time stats
    streaming
    base URI
    ...

    View Slide

  17. 379 requests in
    HTTP/2
    0,3 s!

    View Slide

  18. View Slide

  19. View Slide

  20. What’s next? Your contrib!
    TraceableHttpClient, profiler panel, logger
    integration, mock client, record/replay, raw
    sockets, cookie jar, ...

    View Slide

  21. R.I.P. Goutte
    Integrates with battle-tested components
    HttpClient
    + BrowserKit
    + DomCrawler
    + CssSelector
    + HttpCache

    View Slide

  22. View Slide

  23. View Slide

  24. Back to the basics...
    part 4/n
    Fabien Potencier
    @fabpot

    View Slide

  25. 4) Symfony MIME
    Everything you need to create beautiful emails
    Fabien Potencier
    @fabpot

    View Slide

  26. Symfony Mime

    View Slide

  27. use Symfony\Component\Mime\Email;
    $email = (new Email())
    ->from('[email protected]')
    ->to('[email protected]')
    ->subject('Some subject')
    ->text('Some text message')
    ->html('Some HTML message')
    ->attach('doc.txt')
    ;
    The basics

    View Slide

  28. $email = (new Email())
    ->from('[email protected]')
    ->to(new Address('[email protected]'))
    ->addTo(new NamedAddress('[email protected]', 'Fabien'))
    ->addCc('[email protected]', '[email protected]')
    ->addCc(...['[email protected]', '[email protected]'])
    ->subject('Some subject')
    ->text('Some text')
    ;
    from, to, cc, bcc

    View Slide

  29. $email = (new Email())
    ->from('[email protected]')
    ->to('[email protected]')
    ->subject('Some subject')
    ->text('Some text message')
    ->html('Some HTML message')
    ;
    echo strlen(serialize($email));
    Email is a data object
    Only 2k
    vs
    16k for Swiftmailer

    View Slide

  30. Why is it so different

    from Swiftmailer?

    View Slide

  31. $email = (new Email())
    ->text('Some text message')
    ->html('Some HTML message')
    ;
    $email = (new \Swift_Message())
    ->setBody('Some text message')
    ->addPart('Some HTML message', 'text/html')
    ;
    A better data object model
    16k serialized
    38 objects
    complex serialization
    "fixed" headers
    2k serialized
    7 objects
    simple serialization
    "dynamic" headers

    View Slide

  32. echo $email->toString();
    sleep(2);
    $email->to('[email protected]');
    echo $email->toString();
    Fixed vs dynamic headers
    Different

    set of headers
    Date, Boundary, Message-ID

    View Slide

  33. $email = (new Email())
    ->from('[email protected]')
    ->to('[email protected]')
    ->subject('Some subject')
    ->text(fopen('email.txt', 'r'))
    ->html(fopen('email.html', 'r'))
    ;
    echo $email->toString();
    foreach ($email->toIterable() as $chunk) {
    echo $chunk;
    }
    String or resources, your choice

    View Slide

  34. // Email extends Message
    use Symfony\Component\Mime\Message;
    use Symfony\Component\Mime\Part\TextPart;
    use Symfony\Component\Mime\Header\Headers;
    $body = new TextPart('Some content');
    $headers = (new Headers())
    ->addMailboxListHeader('From', ['[email protected]'])
    ->addMailboxListHeader('To', ['[email protected]'])
    ->AddTextHeader('Subject', 'Some subject')
    ;
    $email = new Message($headers, $body);
    And you get full control!

    View Slide

  35. $txt = new TextPart('Some content');
    $html = new TextPart('Some content', 'html');
    $body = new AlternativePart($txt, $html);
    $email = new Message($headers, $body);
    Get creative

    View Slide

  36. A "complete" email
    multipart/mixed
    |
    |------------> multipart/related
    | |
    | |------------> multipart/alternative
    | | |
    | | ------------> text/plain
    | | |
    | | ------------> text/html
    | |
    | ------------> image/png
    |
    ------------> application/pdf
    ->text()
    ->html()
    ->embed()
    ->attach()

    View Slide

  37. $email = (new Email())
    ->from('[email protected]')
    ->to('[email protected]')
    ->subject('Some subject')
    ->setBody($body)
    ;
    Mix several approaches

    View Slide

  38. $email
    ->attach('Some content', 'doc.txt', 'text/plain')
    ->attachFromPath('/path/to/doc.txt')
    ->attach(fopen('doc.txt', 'r'), 'doc.txt', 'text/plain')
    ;
    Attachments

    View Slide

  39. $email = (new Email())
    ->from('[email protected]')
    ->to('[email protected]')
    ->subject('Some subject')
    ->text('Some text')
    ->html('The new logo: ')
    ->embedFromPath('logo-small.jpg', 'logo.jpg')
    ;
    Embeds

    View Slide

  40. // Email extends Message extends RawMessage
    use Symfony\Component\Mime\RawMessage;
    $message = new RawMessage($email->toString());
    $message->toString();
    Go raw!
    Serialize an email as
    a string instead of a PHP
    object

    View Slide

  41. Creating Emails
    with Twig
    Twig is perfect for emails
    aka, Twig is not dead and still very useful :)

    View Slide

  42. use Symfony\Bridge\Twig\Mime\Renderer;
    use Symfony\Bridge\Twig\Mime\TemplatedEmail;
    use Twig\Environment;
    use Twig\Loader\FilesystemLoader;
    use Symfony\Component\Mime\NamedAddress;
    $twig = new Environment($loader = new FilesystemLoader(__DIR__.'/templates'));
    $loader->addPath(__DIR__.'/images', 'images');
    $email = (new TemplatedEmail())
    ->from('[email protected]')
    ->to(new NamedAddress('[email protected]', 'Fabien'))
    ->text('Some text content')
    ->htmlTemplate('simple.html.twig')
    ->context([
    'city' => 'Lille'
    ])
    ;
    $renderer = new Renderer($twig);
    echo $renderer->render($email)->toString();
    Native integration with Twig

    View Slide


  43. Welcome {{ email.toName }} from {{ city }}!




    Native integration with Twig
    Symfony\Bridge\Twig\Mime\
    WrappedTemplatedEmail
    Twig template name
    Template context

    View Slide

  44. {% do email.attach('@docs/doc.pdf') %}

    Welcome {{ email.toName }}!




    Native integration with Twig

    View Slide

  45. {% do email.priority(5) %}

    Welcome {{ email.toName }}!




    Native integration with Twig

    View Slide

  46. $email = (new TemplatedEmail())
    ->from('[email protected]')
    ->to(new NamedAddress('[email protected]', 'Fabien'))
    ->textTemplate('simple.txt.twig')
    ->htmlTemplate('simple.html.twig')
    ;
    Native integration with Twig

    View Slide

  47. $email = (new TemplatedEmail())
    ->from('[email protected]')
    ->to(new NamedAddress('[email protected]', 'Fabien'))
    ->template('simple.email.twig')
    ;
    Native integration with Twig

    View Slide

  48. {% block config %}
    {% do email.attach('@images/planfaidherbe.jpeg') %}
    {% endblock %}
    {% block subject %}Email Subject{% endblock %}
    {% block text %}
    Optional text representation
    {% endblock %}
    {% block html %}
    Welcome {{ email.toName }}!

    {% endblock %}
    Native integration with Twig

    View Slide

  49. {% block text %}
    {% set formula = "2 > 1?" %}
    {% autoescape false %}
    {{ formula }}
    {% endautoescape %}
    {% endblock %}
    {% block html %}
    {% set formula = "2 > 1?" %}
    {{ formula }}
    {% endblock %}
    Native integration with Twig
    HTML escape
    by default with the "name"
    strategy
    From: [email protected]
    To: Fabien
    MIME-Version: 1.0
    Date: Thu, 28 Feb 2019 12:10:16 +0100
    Message-ID: <[email protected]>
    Content-Type: multipart/alternative;
    boundary="_=_symfony_1551352216_9df84f01f42af586d65b48578466206f_=
    --_=_symfony_1551352216_9df84f01f42af586d65b48578466206f_=_
    Content-Type: text/plain; charset=utf-8
    Content-Transfer-Encoding: quoted-printable
    =20
    2 > 1?
    =20
    --_=_symfony_1551352216_9df84f01f42af586d65b48578466206f_=_
    Content-Type: text/html; charset=utf-8
    Content-Transfer-Encoding: quoted-printable
    =20
    2 > 1?
    --_=_symfony_1551352216_9df84f01f42af586d65b48578466206f_=_--

    View Slide

  50. Tip!
    If the Text part is empty,
    the Renderer automatically generates one

    View Slide

  51. But HTML in emails is hard
    Compatibility with email clients
    Inline CSS
    Responsive layout

    View Slide

  52. use Twig\CssInliner\CssInlinerExtension;
    $twig->addExtension(new CssInlinerExtension());
    {% filter inline_css %}
    <br/>b { color: red }<br/>

    Welcome {{ email.toName }}!

    {% endfilter %}
    Inlining CSS

    View Slide

  53. {% filter inline_css("@css/email.css") %}
    <br/>b { color: red }<br/>

    Welcome {{ email.toName }}!

    {% endfilter %}
    Inlining CSS

    View Slide

  54. use Twig\Markdown\MarkdownExtension;
    $twig->addExtension(new MarkdownExtension());

    {% filter markdown %}
    | Version | LTS? | Latest |
    | ------------- |:-------------:| -------:|
    | 1.0 | Yes | 1.0.1 |
    | 2.1 | No | 2.1.33 |
    {% endfilter %}

    Use Markdown to simplify your templates

    View Slide

  55. use Twig\Inky\InkyExtension;
    $twig->addExtension(new InkyExtension());
    Use Inky to simplify your HTML
    https://foundation.zurb.com/emails.html

    View Slide

  56. {% filter inky|inline_css(source("@zurb/stylesheets/main.css")) %}




    Symfony Connect







    Forgot Your Password?

    It happens. Click the link below to reset it.
    Reset Password

    unsubscribe here.



    {% endfilter %}
    Use Inky to simplify your HTML

    View Slide

  57. What about sending

    our emails now?

    View Slide

  58. Thank you! ❤

    View Slide