Getting started with ReactPHP – Pushing real-time data to the browser (PHPYorkshire)

Getting started with ReactPHP – Pushing real-time data to the browser (PHPYorkshire)

Think about "PHP" for a few seconds… What came to mind? It’s very likely you thought about your average product catalog, a blogging platform or how the platform is inferior to things like Node.js. But wait, it’s 2018! What if I told you PHP’s huge ecosystem has way more to offer and PHP is not inferior at all to its evil cousin Node.js?

In this hands-on tutorial you will learn about the core concepts of async PHP and why you too should care about ReactPHP being a real thing. The workshop has a strong focus on sparking the idea that PHP can be way faster and more versatile than you probably thought. Bring along an open mind and through lots of interesting examples and live demos learn why what sounds crazy at first might soon be a valuable addition in your toolbox.

You’re already familiar with PHP and want to learn what ReactPHP is all about? Then this tutorial is for you! We will start from scratch and build a demo application that pushes data from your command line in real-time to your browser. Several scenarios are prepared, but ideally you bring in your own ideas: Let’s build an interactive chat bot, an interactive CLI tool or even an actual desktop GUI, it’s up to you!

The tutorial assumes people are familiar with PHP, have PHP and their favorite IDE already setup, but does not require people to be familiar with ReactPHP.

---

These slides were used as part of a hands-on workshop at @PHPYorkshire. The full workshop took 3h with basic project setup, getting started with ReactPHP's core components and eventually implementing an HTTP server using Server-Sent Events (EventSource).

Resulting source code can be found here: https://gist.github.com/clue/6ba091ed298b1ecec528a3a6c201a2d1

D1b6700884ac0ae368918ad171bb6a75?s=128

Christian Lück

April 13, 2018
Tweet

Transcript

  1. 4.
  2. 5.

    Agenda - Hello! - Introduction to async PHP with ReactPHP

    - event loops - streaming data - sockets 5
  3. 6.

    Agenda - Hello! - Introduction to async PHP with ReactPHP

    - event loops - streaming data - sockets - promises 6
  4. 7.

    Agenda - Hello! - Introduction to async PHP with ReactPHP

    - event loops - streaming data - sockets - promises - real time data 7
  5. 8.

    Agenda - Hello! - Introduction to async PHP with ReactPHP

    - event loops - streaming data - sockets - promises - real time data - Streaming HTTP 8
  6. 9.

    Agenda - Hello! - Introduction to async PHP with ReactPHP

    - event loops - streaming data - sockets - promises - real time data - Streaming HTTP - Chat bots 9
  7. 10.

    Agenda - Hello! - Introduction to async PHP with ReactPHP

    - event loops - streaming data - sockets - promises - real time data - Streaming HTTP - Chat bots - interactive CLI tools 10
  8. 11.

    Agenda - Hello! - Introduction to async PHP with ReactPHP

    - event loops - streaming data - sockets - promises - real time data - Streaming HTTP - Chat bots - interactive CLI tools - desktop GUI 11
  9. 12.

    Agenda - Hello! - Introduction to async PHP with ReactPHP

    - event loops - streaming data - sockets - promises - real time data - Streaming HTTP - Chat bots - interactive CLI tools - desktop GUI - Conclusions 12
  10. 17.

    Agenda - Hello! - Introduction to async PHP with ReactPHP

    - event loops - streaming data - sockets - promises 17
  11. 18.

    Agenda - Hello! - Introduction to async PHP with ReactPHP

    - event loops - streaming data - sockets - promises - event-driven, streaming application development - Conclusions 18
  12. 19.
  13. 30.

    Who are you? 30 now that you know me… -

    PHP developers? - architecs / engineers?
  14. 31.

    Who are you? 31 now that you know me… -

    PHP developers? - architecs / engineers? - know React?
  15. 32.

    32

  16. 36.

    PHP and the web of the ‘90s - traditional LAMP

    stack - Request-Response-Cycle - PHP is too slow? 36 Apache Client PHP MySQL
  17. 37.

    PHP and the web of the ‘90s - traditional LAMP

    stack - Request-Response-Cycle - PHP is too slow? - We sure can improve this… 37 Apache Client PHP MySQL
  18. 38.

    PHP and the web of the ‘90s - traditional LAMP

    stack - Request-Response-Cycle - PHP is too slow? - We sure can improve this… 38 Apache Client PHP MySQL Apache Client FPM MySQL PHP PHP
  19. 39.

    PHP and the web of the ‘90s - traditional LAMP

    stack - Request-Response-Cycle - PHP is too slow? - We sure can improve this… 39 Apache Client PHP MySQL Apache Client FPM MySQL PHP PHP nginx Client FPM MySQL PHP PHP
  20. 40.

    PHP and the web of the ‘90s - traditional LAMP

    stack - Request-Response-Cycle - PHP is too slow? - We sure can improve this… 40 Apache Client PHP MySQL Apache Client FPM MySQL PHP PHP nginx Client FPM MySQL PHP PHP nginx Client FPM memcache PHP PHP MySQL
  21. 45.

    Knock knock! 2018! - Separation of concerns (Frontend↔Backend) - HTTP

    APIs (RESTful) - Integration with 3rd parties - Live-Data (ticker) - CLI tools Who’s there? 45
  22. 47.
  23. 53.
  24. 64.

    I/O is everywhere third party HTTP APIs (RESTful, SOAP, you

    name it…) mysql, postgres filesystem I/O (session files) 64
  25. 65.

    I/O is everywhere third party HTTP APIs (RESTful, SOAP, you

    name it…) mysql, postgres filesystem I/O (session files) redis, memcache 65
  26. 71.
  27. 72.

    This is React 72 Start multiple I/O operations (non-blocking) Get

    notified when something happens (react) Don’t waste time waiting
  28. 75.

    What React is not React is not black magic /

    vodoo React is not a framework 75
  29. 76.

    What React is not React is not black magic /

    vodoo React is not a framework React is not the new buzz 76
  30. 80.

    Event loop Consumers - THE core, low-level component - Create

    an instance - Just use the Factory - Additional extensions for bigger payloads - something inbetween… - just pass the $loop around - Start running - keeps running forever - unless stopped or done 80
  31. 81.

    Event loop Consumers - THE core, low-level component - Create

    an instance - Just use the Factory - Additional extensions for bigger payloads - something inbetween… - just pass the $loop around - Start running - keeps running forever - unless stopped or done 81 $loop = Factory::create(); // something inbetween // pass the $loop around to all components $loop->run();
  32. 83.

    Event loop Implementors - Reactor pattern (hence the name) -

    start timers - once - periodic - ticks 83 $loop->addTimer(0.5, function () { echo ‘world’; }); $loop->addTimer(0.3, function () { echo ‘hello’; });
  33. 84.

    Event loop Implementors - Reactor pattern (hence the name) -

    start timers - once - periodic - ticks - wait for stream resources to become - readable - writable 84 $loop->addTimer(0.5, function () { echo ‘world’; }); $loop->addTimer(0.3, function () { echo ‘hello’; }); $loop->addReadStream($stream, $fn); $loop->addWriteStream($stream, $fn);
  34. 85.

    85

  35. 87.

    Streams - Process large strings in chunks as they happen

    (think downloads) - Types - Readable (e.g. STDIN pipe) - Writable (e.g. STDOUT pipe) - Duplex (e.g. TCP/IP connection) 87
  36. 88.

    Streams - interfaces, events and listeners: 88 $dest->write(‘hello’); $source->on(‘data’, function

    ($data) { var_dump($data); }); $source->on(‘close’, function () { echo ‘stream closed’; });
  37. 89.

    Streams - interfaces, events and listeners: 89 $dest->write(‘hello’); $source->on(‘data’, function

    ($data) { var_dump($data); }); $source->on(‘close’, function () { echo ‘stream closed’; }); $source->pipe($gunzip)->pipe($badwords)->pipe($dest);
  38. 90.

    90

  39. 94.

    Sockets 94 - Streams, but over the network - servers

    listen - clients connect - Focus on TCP/IP (UDP etc. also possible)
  40. 95.

    95

  41. 99.

    Sockets in practice - implementation detail - higher level protocols

    (HTTP anybody) - higher level concepts (RESTful etc.) 99
  42. 100.

    Sockets in practice - implementation detail - higher level protocols

    (HTTP anybody) - higher level concepts (RESTful etc.) - higher level APIs (SDKs, API clients etc.) 100
  43. 101.

    Sockets in practice - implementation detail - higher level protocols

    (HTTP anybody) - higher level concepts (RESTful etc.) - higher level APIs (SDKs, API clients etc.) - Concepts still apply, details are hidden 101
  44. 103.

    Promises - Placeholder for a single future result - Possible

    states: - pending - fulfilled (successfully resolved) - rejected (Exception occured) 103
  45. 104.

    Promises - no more imperative code flow - instead (tell,

    don’t ask) 104 $a->then($fulfilled = null, $rejected = null); $a->then(‘process’); $a->then(‘process’, ‘var_dump’);
  46. 105.

    Promises in practice - Everywhere! - react/socket - clue/buzz-react -

    clue/packagist-react - clue/redis-react - react/mysql 105
  47. 106.

    106

  48. 108.

    HTTP streaming 108 - HTTP request/response semantics - streaming responses

    (download huge files) - streaming requests (upload huge files) - Still request/response semantics - Long-polling (Comet) anyone?
  49. 112.

    Server-Sent Events in a gist 112 - Normal Request/Response -

    Client API for streaming access HTTP/1.1 200 OK Content-Type: text/event-stream
  50. 113.

    Server-Sent Events in a gist 113 - Normal Request/Response -

    Client API for streaming access HTTP/1.1 200 OK Content-Type: text/event-stream data: hello
  51. 114.

    Server-Sent Events in a gist 114 - Normal Request/Response -

    Client API for streaming access HTTP/1.1 200 OK Content-Type: text/event-stream data: hello data: world
  52. 115.

    115

  53. 116.

    Server sent events clue/sse-react - Server sent events (SSE) -

    aka. EventSource (browser API) - Streaming events to browser - limited browser support 116
  54. 119.

    Websocket server cboden/ratchet - Async WebSocket server - bidirectional data

    flow between browser and server - better browser support 119
  55. 120.
  56. 122.

    122

  57. 125.
  58. 131.
  59. 132.
  60. 136.

    Need help? Want to help? - check each component’s README

    - check open issues - join #reactphp on irc.freenode.org - tweet @ReactPHP or #reactphp 136
  61. 137.

    Need help? Want to help? - check each component’s README

    - check open issues - join #reactphp on irc.freenode.org - tweet @ReactPHP or #reactphp - Talk to me 137
  62. 138.

    Need help? Want to help? - check each component’s README

    - check open issues - join #reactphp on irc.freenode.org - tweet @ReactPHP or #reactphp - Talk to me Did I mention I’m available? 138
  63. 141.

    Avoid blocking! - The loop must not be blocked -

    Many functions / lib assume blocking by default - Anything >1ms should be reconsidered 141
  64. 142.

    Avoid blocking! - The loop must not be blocked -

    Many functions / lib assume blocking by default - Anything >1ms should be reconsidered - Alternatives - Single result: Promises - Evented: Streams 142
  65. 143.

    Avoid blocking! - The loop must not be blocked -

    Many functions / lib assume blocking by default - Anything >1ms should be reconsidered - Alternatives - Single result: Promises - Evented: Streams - Need a blocking function? - Fork off! - Use IPC 143
  66. 144.

    Avoid blocking! - The loop must not be blocked -

    Many functions / lib assume blocking by default - Anything >1ms should be reconsidered - Alternatives - Single result: Promises - Evented: Streams - Need a blocking function? - Fork off! - Use IPC 144 Pay attention: - PDO, mysql etc. - file system access - network access - third-party APIs
  67. 146.

    Integration with traditional environments 146 integrating async into sync is

    easy - just run the loop until you’re done - see clue/block-react
  68. 147.

    Integration with traditional environments 147 integrating async into sync is

    easy - just run the loop until you’re done - see clue/block-react integrating sync into async is hard
  69. 148.

    Integration with traditional environments 148 integrating async into sync is

    easy - just run the loop until you’re done - see clue/block-react integrating sync into async is hard - often requires async rewrite - consider forking instead