This repository has been archived on 2025-01-19. You can view files and clone it, but cannot push or open issues or pull requests.
oliverdavies.uk-old-sculpin/source/_posts/2019-09-13-live-blogging-symfonylive-london.md

441 lines
15 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Live Blogging From SymfonyLive London 2019
tags:
- conference
- symfony
- symfonylive
- php
---
Inspired by [Matt Stauffer](https://twitter.com/stauffermatt)'s [live blogging of the keynote](https://mattstauffer.com/blog/introducing-laravel-vapor) at Laracon US, Im going to do the same for the sessions that Im attending at [SymfonyLive London 2019](https://london2019.live.symfony.com)...
## Keynote (Back to the basics)
**Embrace the Linux philosophy**
* How we grow the Symfony ecosystem. Built abstracts.
* HttpFoundation, HttpKernel
* Moved to infrastructure
* A few abstractions on top of PHP. Improved versions of PHP functions (`dump` and `var_dump`)
* Started a add higher level abstractions (e.g. Mailer), built on the lower ones.
* Recently worked on PHPUnit assertions. Mailer in Symony 4.4. Can test if an email is sent or queued
**Building flexible high-level abstractions on top of low-level ones**
### What's next?
* Mailer announced in London last year. New component.
* System emails? e.g. new customer, new invoice.
* Symfony Mailer = Built-in responsive, flexible, and generic system emails
- Twig with TwigExtraBundle
- Twig `inky-extra` package (Twig 1.12+)
- Zurb Foundation for Emails CSS stylesheet
- Twig `cssinliner-extra` package (Twig 1.12+)
- Optimised Twig layouts
* `SystemEmail` class extends templated email
* Can set importance,
* Customisable
* Always trying to keep flexible, so things can be overidden and customised
### Sending SMS messages
* new `Texter` and `SmsMessage` class for sending SMS messages
* Same abstraction as emails, but for SMS messages
* Based on HttpClient + Symfony Messenger and third-party providers (Twilio and Nexmo) `twilio://` and `nemxo://`
* Can set via transport `$sms->setTransport('nexmo')`
* Extend the `SystemEmail` and do what you want
* Failover
### Sending Messages
* Create `ChatMessage`
* Telegram and Slack
* `$message->setTransport('telegram')`, `$bus->dispatch($message)`
* Send to Slack **and** Telegram
* `SlackOptions` and `TelegramOptions` for adding emojis etc
* Common transport layer `TransportInterface`, `MessageInterface`
* Failover - e.g. if Twilio is down, send to Telegram
### New component - SymfonyNotifier
* Channels - email, SMS, chat
* Transport, slack, telegram, twilio
* Create a notification, arguments are message and transports (array)
* Receiver
* Customise notifications, `InvoiceNotification` extends `Notification`. `getChannels`
* Override default rendering
* `ChatNotificationInterface` - `asChatMessage()`
* Semantic configuration
* `composer req twilio-notifier telegram-notifier`
* Channels
- Mailer
- Chatter
- Texter
- Browser
- Pusher (iOS, Android, Desktop native notifications)
- Database (web notification centre)
- **A unified way to notify Users via a unified Transport layer**
* Each integration is only 40 lines of code
### What about a SystemNotification?
* Autoconfigured channels
* `new SystemNotification`, `Notifier::getSystemReceivers`
* Importance, automatically configures channels
* Different channels based on importance
* `ExceptionNotification` - get email with stack trace attached
Notifier
* send messages via a unified api
* send to one or many receivers
* Default configu or custom one
### How can we leverage this new infrastructure?
* `Monolog NotifierHandler` - triggered on `Error` level logs
* Uses notified channel configuration
* Converts Error level logs to importance levels
* Configurablelike other Notifications
* 40 lines of code
* Failed Messages Listener - 10 lines of glue code
* **Experimental component in 5.0**
* Can't in in 4.4 as it's a LTS version
* First time an experimental component is added
* Stable in 5.1
## Queues, busses and the Messenger component (Tobias Nyholm)
* Stack is top and buttom - Last-in, first-out
* Queue is back and front - last in, first out
### 2013
* Using Symfony, used 40 or 50 bundles in a project - too much information!
* Used to copy and paste, duplicate a lot of code
* Testing your controllers - controllers as services?
* Controllers are 'comfortable'
* Tried adding `CurrentUserProvider` service to core, should be passed as an argument. Cannot test.
* 'Having Symfony all over the place wasn't the best thing' - when to framework (Matthias Noback)
- Hexagonal architecture
- Keep your kernel away from infrastructure. Let the framework handle the infrastructure.
* Controller -> Command -> Command Bus -> `CommandHandler`
#### What did we win?
* Can leverage Middleware with a command bus
* Queues as a service (RabbitMQ)
* Work queue - one producer, multiple consumers
* Queues should be durable - messages are also stored on disk, consumers should acknowledge a message once a message is handled
* Publish/subscribe
- Producer -> Fanout/direct with routing (multiple queues) -> multiple consumers
* Topics - wildcards
### 2016
* New intern. Understand everything, 'just PHP'. Plain PHP application, not 'scary Symfony'
### Symfony Messenger
* `composer req symfony/messager` - best MessageBus implementation
* Message -> Message bus -> Message handler
* Message is a plain PHP class
* Handler is a normal PHP class which is invokable
* `messenger:message_hander` tag in config
* Autowire with `MessageHandlerInterface`
* What if it takes 20 seconds to send a message? Use asynchronous.
* Transports as middleware (needs sender, receiver, configurable with DSN, encode/decode). `MESSENGER_DSN` added to `.env`
* Start consumer with `bin/console messager:consume-messages`. Time limit with `--time-limit 300`
* PHP Enqueue - production ready, battle-tested messaging solution for PHP
### Issues
* Transformers, takes an object and transforms into an array - `FooTransformer implements TransformerInterface`.
* Don't break other apps by changing the payload.
#### Multiple buses
* Command bus, query bus, event bus
* Separate actions from reactions
#### Envelope
* Stamps for metadata - has the item been on the queue already?
#### Failures
* Requeue, different queue or same queue after a period of time
* Failed queue 1 every minute, failed queue 2 every hour - temporary glitches or a bug?
#### Creating entities
* What if two users registered at the same tiem? Use uuids rather than IDs.
* Symfony validation - can be used on messages, not just forms.
* Cache everything
- Option 1: HTTP request -> Thin app (gets responses from Redis) -> POST to queue. Every GET request would warm cache
- Option 2: HTTP request -> Thin app -> return 200 response -> pass to workers
* Tip: put Command and CommandHandlers in the same directory
## HttpClient (Nicolas Grekas)
* new symfony component, released in may
* Httpclient contracts, separate package that contains interfaces
* Symfony
* PHP-FIG
* Httplug
* `HttpClient::create()`. `$client->get()`
* JSON decoded with error handling
* Used on symfony.com website (#1391). Replaces Guzzle `Client` for `HttpClientInterface`
* Object is stateless, Guzzle is not. Doesn't handle cookies, cookies are state
* Remove boilerplate - use `toArray()`
* Options as third argument - array of headers, similar to Guzzle
### What can we do with the Response?
* `getStatusCode(): int`
* `getHeaders(): array`
* `getContent(): string`
* `toArray(): array`
* `cancel(): void`
* `getInfo(): array` - metadata
* Everything is lazy!
* 80% of use-cases covered
### What about PSR-18?
* Decorator/adapter to change to PSR compatible
* Same for Httplug
### What about the remaining 20%?
* Options are part of the abstraction, not the implementation
#### Some of the options
* `timeout` - control inactivity periods
* `proxy` - get through a http proxy
* `on_progress` - display a progress bar / build a scoped client
* `base_url` - resolve relative URLS / build a scoped client
* `resolve` - protect webhooks against calls to internal endpoints
* `max_redirects` - disable or limit redirects
* Robust and failsafe by default
* Streamable uploads - `$mimeParts->toIterable()`.
* donwload a file
```php
foreach ($client->stream($response) as $chunk) {
// ...
}
```
- Responses are lazy, requests are concurrent
- Asychronus requests. Reading in network order
```
foreach ($client->stream($responses) as $response => $chunk) {
if ($chunk->isLast()) {
// a $response completed
} else {
// a $response's got network activity or timeout
}
}
```
* 379 request completed in 0.4s!
* `Stream` has second argument, max number of seconds to wait before yielding a timeout chunk
* `ResponseInterface::getInfo()` - get response headers, redirect count and URL, start time, HTTP method and code, user data and URL
* `getInfo('debug')` - displays debug information
### The components
* `NativeHttpClient` and `CurlHttpClient`
- both provide
+ 100% contracts
+ secure directs
+ extended (time) info
+ transparent HTTP compression and (de)chunking
+ automatic HTTP proxy configuration via env vars
#### `NativeHttpClient`
- is most portable, works for everyone
- based on HTTP stream wrapper with fixed redirect logic
- blocking until response headers arrive
#### `CurlHttpClient`
- Requires ext-curl with fixed redirection logic
- Multiplexing response headers and bodies
- Leverages HTTP/2 and PUSH when available
- Keeps connections open also between synchronous requests, no DNS resolution so things are faster
#### Decorators
- ScopingHttpClient - auto-configure options based on request URL
- MockHttpClient - for testing, doesn't make actual HTTP requests
- CachingHttpClient - adds caching on a HTTP request
- Psr18Client
- HttplugClient
- TraceableHttpClient
### Combining
#### FrameworkBundle/Autowiring
```yml
framework:
http_client:
max_host_connections: 4
deault_options:
# ....
scoped_client:
# ...
```
#### HttpBrowser
* HttpClient + DomCrawler + CssSelector + HttpKernel + BrowserKit
* RIP Goutte!
### Coming in 4.4...
- `max_duration`
- `buffer` based on a callable
- `$chunk->isInformational()`
- `$response->toStream()`
- Async-compatible extensibility, when decoration is not enough
`composer req symfony/http-client`
## Symfony Checker is coming (Valentine Boineau)
* Static analysis tool for Symfony
- Does a method exist?
- Is it deprecated?
* insight.symfony.com
* @symfonyinsight
* Released soon
### Differences
* Specialise in Symfony - can see more relevant things
* Different interface to other services
## Feeling unfulfilled by SPA promises? Go back to Twig (Dan Blows)
A way on the front-end JS, CSS, images at the beginning of the request, sends a HTTP request (XHR/AJAX) to the back-end
### Why SPAs?
- A way on the front-end JS, CSS, images at the beginning of the request, sends a HTTP request (XHR/AJAX) to the back-end
- no full page refresh
- Supposed to be much quicker
- 'Right tool for the job' - JS on the front-end, PHP on the back-end
- Division of responsibility == faster development
- Reusable API - Api -> Mobile App and SPA - easy to add another consumer
- Easier to debug?
### Why not SPAs?
- Lots of HTTP requests (400 to load the initial page on one project) == slow front end
- Blurred responsibilities == tightly coupled teams
- harder to debug, bugs fall between systems and teams. Huge gap between front-end and back-end, passing responsibilites.
- You can fix these problems in SPAs, but is it worth it?
+ Examples of good SPAs - Trello, Flickr
### Using Twig as an alternative to an SPA?
#### Faster UI - Try and figure out where the problem is.
If you're trying to speed things up, find out where the problem is.
* Browser tools
* Web Debug Toolbar
* Blackfire
* Optimise and monitor
#### Speed up Twig
- Speeding up Symfony
- ext/twig (PHP5 only, not PHP 7)
- Store compiled templates in Opcache, make sure it's enabled
- Render assets though the webserver (assetic not running all the time)
#### Edge side includes
- Component cached differently to the rest of the page
- Varnish/Nginx
- `render_esi`
- News block that caches frequently, rest of the page
#### HTTP/2 with Weblink
- slow finding CSS files to load - 'push' over CSS files, doesn't need to wait
- `preload()` - https://symfony.com/doc/current/web_link.html
#### Live updating pages
- Instantly update when sports results are updated, news articles are added
- Mercure - https://github.com/symfony/mercure
- LiveTwig - whole block or whole section, and live update `render_live`
- Turbolinks - replace whole body, keeps CSS and JS in memory. Merges new stuff in. `helthe/turbolinks`
- ReactPHP - shares kernel between requests
### Writing better code with Twig
- Keep templates simple. Avoid spaghetti code, only about UI. HTML or small amounts of Twig.
- Avoid delimeter chains
- Bad:`blog_post.authors.first.user_account.email_address`
- Good `{{ blog_post.authors_email_address }}`
- Less brittle, slow
* Filters
- Use filters to be precise
- Custom filters
- Avoid chains. Can cause odd results. Create a new filter in PHP
* Functions
- Write your own functions
- Simpler templates
- Get data, can use boolean statements
* Components
- Break a page into components rather than one large page
- `include()`
- Use `only` to only pass that data. less tightenly coupled.
* `render` calls the whole of Symfony, boots Kernel, can be expensive and slow
* Loosely couple templates and controllers
- Keep responses simple
- What makes sense
- if you need extra data in the template, get it in the template
* View models
- Mixed results
- `BlogPostViewModel`
- Can result in boilerplate code
- Can be useful if the view model is different to the Entity
* DRY
- "Don't repeat yourself"
+ Faster development
* Separate UI tests from back-end tests. Different layers for different teams. People don't need to run everything if they are only changing certain things.
- Help your front end
+ Webpack - Encore
+ Type hinting in functions and filters, easier to debug
+ Logging
+ Friendly exceptions - help front-end devs by returning meaningful, readbale errors
+ Web Debug Toolbar and Profiler, provide training for toolbar and profilers
+ Twig-friendly development environment - Twig support in IDEs and text editors
SPAs are sometimes teh right solution. Why do they want to use it, can the same benefits be added with Twig?
3 most important points:
- Profile, identidy, optimise, monitor
- Loosely couple templates to your app code
- Help your front ends - put your front end developers first
- You don't need to use a SPA for single pages, use JavaScript for that one page. It doesn't need to be all or nothing.
## BDD Your Symfony Application (Kamil Kokot)
* Applying BDD to Sylius
* 2 years since release of Sylius (Symfony 2 alpha)
* The business part is more important than the code part
### What is BDD?
* Behaviour driven development. Combines TDD and DDD, into an agile methodology
* Encourages communicatio
* Creates shared understanding
* Living, executable documentation
## Migrating to Symfony one route at a time (Steve Winter)
## Closing Keynote: The fabulous World of Emojis and other Unicode symbols (Nicolas Grekas)