SlideShare a Scribd company logo
1 of 140
Download to read offline
You Got Async
in my PHP!
PRESENTED BY:
Chris Tankersley
Senior PHP Developer Advocate
@dragonmantank
What is
Async?
2
It Depends
3
Procedural
Programming
4
Do this, then this, then this
$t = new Twitter(new HttpClient());
$tweets = $t->getTweets('dragonmantank');
$template = new Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
Procedural Programming
• Single Threaded
• Very susceptible to blocking
operations
• Easy to write
5
Make
Twitter
Object
Make
HTTP
Object
Get
Tweets
Read
Template
Render
Template
6
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
7
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
8
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new HttpClient()
9
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new HttpClient()
require_once 'src/HttpClient.php'
10
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new HttpClient()
11
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new Twitter();
12
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new Twitter();
require_once 'src/Twitter.php'
13
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new Twitter();
require_once 'src/Twitter.php'
getenv('TWITTER_KEY')
14
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new Twitter();
require_once 'src/Twitter.php'
15
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new Twitter();
require_once 'src/Twitter.php'
getenv('TWITTER_SECRET')
16
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new Twitter();
require_once 'src/Twitter.php'
17
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new Twitter();
18
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
19
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
$t->getTweets()
20
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
$t->getTweets()
$httpClient->get($url)
21
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
$t->getTweets()
22
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
23
Wait, how does
PHP avoid
blocking?
24
Wait, how does
PHP avoid
blocking?
Web Servers, like Apache,
are multi-threaded
PHP-FPM spins up
multiple threads for use
Parallel
Computing
Do this, this, and this at the same
time
$reports = [
new DailyBalance(),
new EndOfDay(),
new ProfitLossUpdate(),
];
foreach ($reports as $r) {
$pid = pcntl_fork();
if ($pid === 0) {
$r->run();
exit();
}
}
25
Parallel Programming
• Multiple Threads
• Lets the OS/CPU handle scheduling
• Can be tricky to write
26
Make
Report
Objects
Run Daily
Balance
Report Run End of
Day Report
Run
Profit-Loss
Report
End
27
Main Thread
main()
28
Main Thread
main()
foreach($report)
29
Main Thread
main()
foreach($report)
pcntl_fork()
30
Main Thread
main()
foreach($report)
pcntl_fork()
Daily Balance Thread
main()
31
Main Thread
main()
foreach($report)
pcntl_fork()
Daily Balance Thread
main()
if ($pid > 0)
if ($pid > 0)
32
Main Thread
main()
foreach($report)
pcntl_fork()
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
33
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
34
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()pcntl_fork()
End Of Day Thread
main()
35
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()pcntl_fork()
End Of Day Thread
main()
if ($pid > 0)
if ($pid > 0)
36
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()pcntl_fork()
End Of Day Thread
main()
if ($pid > 0)
$r->run()
37
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
End Of Day Thread
main()
if ($pid > 0)
$r->run()
38
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
End Of Day Thread
main()
if ($pid > 0)
$r->run()pcntl_fork()
39
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
End Of Day Thread
main()
if ($pid > 0)
$r->run()pcntl_fork()
Profit/Loss Thread
main()
40
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
End Of Day Thread
main()
if ($pid > 0)
pcntl_fork()
Profit/Loss Thread
main()
if ($pid > 0)
if ($pid > 0)
41
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
End Of Day Thread
main()
pcntl_fork()
Profit/Loss Thread
main()
if ($pid > 0)
$r->run()
42
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
Profit/Loss Thread
main()
if ($pid > 0)
$r->run()
43
Main Thread
main()
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
Profit/Loss Thread
main()
if ($pid > 0)
$r->run()
44
Main Thread
main()
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
Profit/Loss Thread
main()
if ($pid > 0)
$r->run()
pcntl_wait()
45
Main Thread
main()
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
Profit/Loss Thread
main()
if ($pid > 0)
$r->run()
pcntl_wait()
46
Main Thread
main()
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
Profit/Loss Thread
main()
if ($pid > 0)pcntl_wait()
47
Main Thread
main()
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
Profit/Loss Thread
main()
pcntl_wait()
48
Main Thread
main()
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
Profit/Loss Thread
pcntl_wait()
49
Main Thread
main()
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
pcntl_wait()
Async
Programming
Try and do this, this, and this, as
simultaneously as possible
$loop = EventLoop::create();
$loop->addEvent(function () {
echo "Function 1" . PHP_EOL;
return rand(1,10);
}, function($num) {
echo "Square: " . ($num * $num) .
PHP_EOL;
});
$loop->addEvent(function () {
echo "Function 2". PHP_EOL;
}, function() {
echo "Function 4" . PHP_EOL;
});
$loop->run();
50
Async Programming
• Single Threaded
• Uses an event loop
• Allows quick executions
between larger blocking
operations
51
Event loop ends
Queue
Empty?
Execute
job
Has
callback?
Add to
queue
Start Event
Loop
Yes
Yes No
No
52
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
53
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
54
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
EventLoop::create()
55
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
EventLoop::create()
new EventLoop()
56
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
EventLoop::create()
new EventLoop()
$this->eventQueue = new SplQueue();
Event
Queue
57
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
EventLoop::create()
new EventLoop()
Event
Queue
58
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
EventLoop::create()
Event
Queue
59
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
Event
Queue
60
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
Event
Queue
61
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
addEvent($event1, $callback1)
Event
Queue
62
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
addEvent($event1, $callback1)
$this->eventQueue->enqueue([
$event1, $callback1
]);
Event
Queue
$event1
63
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
addEvent($event1, $callback1)
Event
Queue
$event1
64
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
Event
Queue
$event1
65
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
Event
Queue
$event1
66
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
addEvent($event2, $callback2)
Event
Queue
$event1
67
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
addEvent($event2, $callback2)
$this->eventQueue->enqueue([
$event2, $callback2
]);
Event
Queue
$event1 $event2
68
$loop = EventLoop::create();
$loop->addEvent($event1, $callback2);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
addEvent($event2, $callback2)
Event
Queue
$event1 $event2
69
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
Event
Queue
$event1 $event2
70
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
Event
Queue
$event1 $event2
71
Call Stack
main()
run()
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php
Event
Queue
$event1 $event2
72
Call Stack
main()
run()
foreach ($this->eventQueue as $event)
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php
echo "Function 1" . PHP_EOL;
return rand(1,10);
$event[0]
Event
Queue
$event2
73
Call Stack
main()
run()
foreach ($this->eventQueue as $event)
$return = $event[0]()
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php
echo "Function 1" . PHP_EOL;
return rand(1,10);
$event[0]
Event
Queue
$event2
74
Call Stack
main()
run()
foreach ($this->eventQueue as $event)
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php
5
$return
Event
Queue
$event2
75
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
if (!is_null($event[1]))
5
$return
Event
Queue
$event2
76
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
if (!is_null($event[1]))
5
$return
$this->addEvent($wrappedCallback)
Event
Queue
$event2 $callback1
77
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
if (!is_null($event[1]))
5
$return
Event
Queue
$event2 $callback1
78
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
echo "Function 2". PHP_EOL;
$event[0]
Event
Queue
$callback1
79
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
echo "Function 2". PHP_EOL;
$event[0]
Event
Queue
$callback1
$return = $event[0]()
80
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
echo "Function 2". PHP_EOL;
$event[0]
Event
Queue
$callback1
$return = $event[0]()
echo
81
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
echo "Function 2". PHP_EOL;
$event[0]
Event
Queue
$callback1
$return = $event[0]()
82
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
echo "Function 2". PHP_EOL;
$event[0]
Event
Queue
$callback1
$return = $event[0]()
83
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
echo "Function 2". PHP_EOL;
$event[0]
Event
Queue
$callback1
$return = $event[0]()
return void
84
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
echo "Function 2". PHP_EOL;
$event[0]
Event
Queue
$callback1
$return = $event[0]()
85
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
void
$return
Event
Queue
$callback1
if (!is_null($event[1]))
86
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
if (!is_null($event[1]))
void
$return
$this->addEvent($wrappedCallback)
Event
Queue
$callback1 $callback2
87
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
if (!is_null($event[1]))
void
$return
Event
Queue
$callback1 $callback2
88
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
void
$return
Event
Queue
$callback1 $callback2
89
Most Async is
just Event Loop
Programming
It is a different way to structure
your program
90
Most Async is
just Event Loop
Programming
It is a different way to structure
your program
Async is not:
• Concurrent
• Non-Blocking
• Multi-threaded
• Magic
Async can help better structure
your logic
91
Async makes you think about
end results, not order of
operations
92
Async
Concepts
in PHP
93
Event Loops
Adding In The Special Sauce
94
Async Programming
95
Event loop ends
Queue
Empty?
Execute
job
Has
callback?
Add to
queue
Start Event
Loop
Yes
Yes No
No
Async Programming
96
Event loop ends
Queue
Empty?
Execute
job
Has
callback?
Add to
queue
Start Event
Loop
Yes
Yes No
No
Event Loops
ReactPHP
97
98
$loop = Factory::create();
$server = new Server(function (ServerRequestInterface $request) {
return new Response(
200,
array(
'Content-Type' => 'text/plain'
),
"Hello worldn"
);
});
$socket = new ReactSocketServer(
isset($argv[1]) ? $argv[1] : '0.0.0.0:0',
$loop
);
$server->listen($socket);
echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) .
PHP_EOL;
$loop->run();
99
$loop = Factory::create();
$server = new Server(function (ServerRequestInterface $request) {
return new Response(
200,
array(
'Content-Type' => 'text/plain'
),
"Hello worldn"
);
});
$socket = new ReactSocketServer(
isset($argv[1]) ? $argv[1] : '0.0.0.0:0',
$loop
);
$server->listen($socket);
echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) .
PHP_EOL;
$loop->run();
100
$loop = Factory::create();
$server = new Server(function (ServerRequestInterface $request) {
return new Response(
200,
array(
'Content-Type' => 'text/plain'
),
"Hello worldn"
);
});
$socket = new ReactSocketServer(
isset($argv[1]) ? $argv[1] : '0.0.0.0:0',
$loop
);
$server->listen($socket);
echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) .
PHP_EOL;
$loop->run();
101
$loop = Factory::create();
$server = new Server(function (ServerRequestInterface $request) {
return new Response(
200,
array(
'Content-Type' => 'text/plain'
),
"Hello worldn"
);
});
$socket = new ReactSocketServer(
isset($argv[1]) ? $argv[1] : '0.0.0.0:0',
$loop
);
$server->listen($socket);
echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) .
PHP_EOL;
$loop->run();
102
$loop = Factory::create();
$server = new Server(function (ServerRequestInterface $request) {
return new Response(
200,
array(
'Content-Type' => 'text/plain'
),
"Hello worldn"
);
});
$socket = new ReactSocketServer(
isset($argv[1]) ? $argv[1] : '0.0.0.0:0',
$loop
);
$server->listen($socket);
echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) .
PHP_EOL;
$loop->run();
103
$loop = Factory::create();
$server = new Server(function (ServerRequestInterface $request) {
return new Response(
200,
array(
'Content-Type' => 'text/plain'
),
"Hello worldn"
);
});
$socket = new ReactSocketServer(
isset($argv[1]) ? $argv[1] : '0.0.0.0:0',
$loop
);
$server->listen($socket);
echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) .
PHP_EOL;
$loop->run();
104
RatchetPHP
105
$socket = new Socket();
$ws = new WsServer($socket);
$ws->setStrictSubProtocolCheck(false);
$server = new App('localhost', '8080', '0.0.0.0');
$server->routes->add(
'events',
new Route('/events', array('_controller' => new EventsController()))
);
$server->routes->add(
'onAnswer',
new Route('/onAnswer', array('_controller' => new AnswerController()))
);
$server->routes->add(
'socket',
new Route('/socket', array('_controller' => $ws))
);
$server->run();
106
$socket = new Socket();
$ws = new WsServer($socket);
$ws->setStrictSubProtocolCheck(false);
$server = new App('localhost', '8080', '0.0.0.0');
$server->routes->add(
'events',
new Route('/events', array('_controller' => new EventsController()))
);
$server->routes->add(
'onAnswer',
new Route('/onAnswer', array('_controller' => new AnswerController()))
);
$server->routes->add(
'socket',
new Route('/socket', array('_controller' => $ws))
);
$server->run();
107
$socket = new Socket();
$ws = new WsServer($socket);
$ws->setStrictSubProtocolCheck(false);
$server = new App('localhost', '8080', '0.0.0.0');
$server->routes->add(
'events',
new Route('/events', array('_controller' => new EventsController()))
);
$server->routes->add(
'onAnswer',
new Route('/onAnswer', array('_controller' => new AnswerController()))
);
$server->routes->add(
'socket',
new Route('/socket', array('_controller' => $ws))
);
$server->run();
108
$socket = new Socket();
$ws = new WsServer($socket);
$ws->setStrictSubProtocolCheck(false);
$server = new App('localhost', '8080', '0.0.0.0');
$server->routes->add(
'events',
new Route('/events', array('_controller' => new EventsController()))
);
$server->routes->add(
'onAnswer',
new Route('/onAnswer', array('_controller' => new AnswerController()))
);
$server->routes->add(
'socket',
new Route('/socket', array('_controller' => $ws))
);
$server->run();
109
public function onMessage(RatchetConnectionInterface $from, $msg)
{
$event = json_decode($msg, true);
if($event) {
switch($event['event']) {
case 'websocket:dtmf':
try {
$uuid = $this->calls[$from->resourceId];
$talk = $this->nexmo->calls()->get(
new Call($uuid)
)
->talk();
$talk->setText('You pressed ' . $event['digit']);
$talk->put();
break;
} catch (Exception $e) {
var_dump('Error: ' . $e->getMessage());
}
break;
}
} else {
file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY);
}
}
110
public function onMessage(RatchetConnectionInterface $from, $msg)
{
$event = json_decode($msg, true);
if($event) {
switch($event['event']) {
case 'websocket:dtmf':
try {
$uuid = $this->calls[$from->resourceId];
$talk = $this->nexmo->calls()->get(
new Call($uuid)
)
->talk();
$talk->setText('You pressed ' . $event['digit']);
$talk->put();
break;
} catch (Exception $e) {
var_dump('Error: ' . $e->getMessage());
}
break;
}
} else {
file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY);
}
}
111
public function onMessage(RatchetConnectionInterface $from, $msg)
{
$event = json_decode($msg, true);
if($event) {
switch($event['event']) {
case 'websocket:dtmf':
try {
$uuid = $this->calls[$from->resourceId];
$talk = $this->nexmo->calls()->get(
new Call($uuid)
)
->talk();
$talk->setText('You pressed ' . $event['digit']);
$talk->put();
break;
} catch (Exception $e) {
var_dump('Error: ' . $e->getMessage());
}
break;
}
} else {
file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY);
}
}
112
public function onMessage(RatchetConnectionInterface $from, $msg)
{
$event = json_decode($msg, true);
if($event) {
switch($event['event']) {
case 'websocket:dtmf':
try {
$uuid = $this->calls[$from->resourceId];
$talk = $this->nexmo->calls()->get(
new Call($uuid)
)
->talk();
$talk->setText('You pressed ' . $event['digit']);
$talk->put();
break;
} catch (Exception $e) {
var_dump('Error: ' . $e->getMessage());
}
break;
}
} else {
file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY);
}
}
113
public function onMessage(RatchetConnectionInterface $from, $msg)
{
$event = json_decode($msg, true);
if($event) {
switch($event['event']) {
case 'websocket:dtmf':
try {
$uuid = $this->calls[$from->resourceId];
$talk = $this->nexmo->calls()->get(
new Call($uuid)
)
->talk();
$talk->setText('You pressed ' . $event['digit']);
$talk->put();
break;
} catch (Exception $e) {
var_dump('Error: ' . $e->getMessage());
}
break;
}
} else {
file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY);
}
}
114
public function onMessage(RatchetConnectionInterface $from, $msg)
{
$event = json_decode($msg, true);
if($event) {
switch($event['event']) {
case 'websocket:dtmf':
try {
$uuid = $this->calls[$from->resourceId];
$talk = $this->nexmo->calls()->get(
new Call($uuid)
)
->talk();
$talk->setText('You pressed ' . $event['digit']);
$talk->put();
break;
} catch (Exception $e) {
var_dump('Error: ' . $e->getMessage());
}
break;
}
} else {
file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY);
}
}
Promises
Pretty wrappers for callbacks
115
Callback Hell
116
Russian Nesting Doll of Sadness
Callbacks Being Passed To More Callbacks
$activeFloridaUsers = array_filter(
array_filter(
array_filter($users, function($user) {
return $user->accountActive();
}, function($user) {
return $user->getBalance() > 0;
}), function($user) {
return $user->getState() === "FL";
}
));
117
Callbacks Being Passed To More Callbacks
$activeFloridaUsers = array_filter(
array_filter(
array_filter($users, function($user) {
return $user->accountActive();
}, function($user) {
return $user->getBalance() > 0;
}), function($user) {
return $user->getState() === "FL";
}
));
118
Callbacks Being Passed To More Callbacks
$activeFloridaUsers = array_filter(
array_filter(
array_filter($users, function($user) {
return $user->accountActive();
}, function($user) {
return $user->getBalance() > 0;
}), function($user) {
return $user->getState() === "FL";
}
));
119
Callbacks Being Passed To More Callbacks
$activeFloridaUsers = array_filter(
array_filter(
array_filter($users, function($user) {
return $user->accountActive();
}, function($user) {
return $user->getBalance() > 0;
}), function($user) {
return $user->getState() === "FL";
}
));
120
Callbacks Being Passed To More Callbacks
$activeFloridaUsers = array_filter(
array_filter(
array_filter($users, function($user) {
return $user->accountActive();
}), function($user) {
return $user->getBalance() > 0;
}), function($user) {
return $user->getState() === "FL";
}
));
121
Callbacks Being Passed To More Callbacks
$activeFloridaUsers = array_filter(
array_filter(
array_filter($users, function($user) {
return $user->accountActive();
}), function($user) {
return $user->getBalance() > 0;
}), function($user) {
return $user->getState() === "FL";
}
));
122
What do Promises provide?
123
• Built off of Promises/A+
• A cleaner interface for callbacks
• A more structured workflow for one logic block to the next
• A way to handle errors in a clean manner
A Cleaner
Callback
Interface
use GuzzleHttpPromisePromise;
$fulfilled = function ($value) {
echo 'The promise was fulfilled.';
};
$rejected = function ($reason) {
echo 'The promise was rejected.';
};
$promise = new Promise();
$promise->then($fulfilled, $rejected);
$promise->resolve();
124
A Cleaner
Callback
Interface
use GuzzleHttpPromisePromise;
$fulfilled = function ($value) {
echo 'The promise was fulfilled.';
};
$rejected = function ($reason) {
echo 'The promise was rejected.';
};
$promise = new Promise();
$promise->then($fulfilled, $rejected);
$promise->resolve();
125
A Cleaner
Callback
Interface
use GuzzleHttpPromisePromise;
$fulfilled = function ($value) {
echo 'The promise was fulfilled.';
};
$rejected = function ($reason) {
echo 'The promise was rejected.';
};
$promise = new Promise();
$promise->then($fulfilled, $rejected);
$promise->resolve();
126
A Cleaner
Callback
Interface
use GuzzleHttpPromisePromise;
$fulfilled = function ($value) {
echo 'The promise was fulfilled.';
};
$rejected = function ($reason) {
echo 'The promise was rejected.';
};
$promise = new Promise();
$promise->then($fulfilled, $rejected);
$promise->resolve();
127
A Cleaner
Callback
Interface
use GuzzleHttpPromisePromise;
$fulfilled = function ($value) {
echo 'The promise was fulfilled.';
};
$rejected = function ($reason) {
echo 'The promise was rejected.';
};
$promise = new Promise();
$promise->then($fulfilled, $rejected);
$promise->then($fulfilled2, $rejected2);
$promise->resolve();
128
$promise = new Promise();
$promise->then(function ($users) {
return array_filter($users, function($user) {
return $user->accountActive();
});
});
$promise->then(function ($activeUsers) {
return array_filter($activeUsers, function($user) {
return $user->getBalance() > 0;
});
});
$promise->then(function ($usersWithBalance) {
return array_filter($usersWithBalance, function($user) {
return $user->getState() === 'FL';
});
});
129
$promise = new Promise();
$promise->then(function ($users) {
return array_filter($users, function($user) {
return $user->accountActive();
});
});
$promise->then(function ($activeUsers) {
return array_filter($activeUsers, function($user) {
return $user->getBalance() > 0;
});
});
$promise->then(function ($usersWithBalance) {
return array_filter($usersWithBalance, function($user) {
return $user->getState() === 'FL';
});
});
130
$promise = new Promise();
$promise->then(function ($users) {
return array_filter($users, function($user) {
return $user->accountActive();
});
});
$promise->then(function ($activeUsers) {
return array_filter($activeUsers, function($user) {
return $user->getBalance() > 0;
});
});
$promise->then(function ($usersWithBalance) {
return array_filter($usersWithBalance, function($user) {
return $user->getState() === 'FL';
});
});
131
$promise = new Promise();
$promise->then(function ($users) {
return array_filter($users, function($user) {
return $user->accountActive();
});
});
$promise->then(function ($activeUsers) {
return array_filter($activeUsers, function($user) {
return $user->getBalance() > 0;
});
});
$promise->then(function ($usersWithBalance) {
return array_filter($usersWithBalance, function($user) {
return $user->getState() === 'FL';
});
});
132
$promise = new Promise();
$promise->then(function ($users) {
return array_filter($users, function($user) {
return $user->accountActive();
});
});
$promise->then(function ($activeUsers) {
return array_filter($activeUsers, function($user) {
return $user->getBalance() > 0;
});
});
$promise->then(function ($usersWithBalance) {
return array_filter($usersWithBalance, function($user) {
return $user->getState() === 'FL';
});
});
133
$promise->resolve($users);
$activeFLUsers = $promise->wait();
134
Getting the Values
$promise->resolve($users);
$activeFLUsers = $promise->wait();
135
Getting the Values
Additional
Takeaways
136
Worker/Queues
137
Horizontally scale work
VONAGE CONFIDENTIAL
Generators and Coroutines
yielding Control Back to the Event Loop
138
Swoole
Like PHP-FPM but has coroutines
139
140
Chris Tankersley
Senior PHP Developer Advocate
at Nexmo
@dragonmantank
chris@ctankersley.com

More Related Content

What's hot

Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome TownRoss Tuck
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsRoss Tuck
 
循環参照のはなし
循環参照のはなし循環参照のはなし
循環参照のはなしMasahiro Honma
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleHugo Hamon
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsMark Baker
 
Debugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 VersionDebugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 VersionIan Barber
 
Things I Believe Now That I'm Old
Things I Believe Now That I'm OldThings I Believe Now That I'm Old
Things I Believe Now That I'm OldRoss Tuck
 
Xlab #1: Advantages of functional programming in Java 8
Xlab #1: Advantages of functional programming in Java 8Xlab #1: Advantages of functional programming in Java 8
Xlab #1: Advantages of functional programming in Java 8XSolve
 
Teaching Your Machine To Find Fraudsters
Teaching Your Machine To Find FraudstersTeaching Your Machine To Find Fraudsters
Teaching Your Machine To Find FraudstersIan Barber
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolveXSolve
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design PatternsHugo Hamon
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistenceHugo Hamon
 
Introdução ao Perl 6
Introdução ao Perl 6Introdução ao Perl 6
Introdução ao Perl 6garux
 
PHP tips and tricks
PHP tips and tricks PHP tips and tricks
PHP tips and tricks Damien Seguy
 
Crafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::ExporterCrafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::ExporterRicardo Signes
 
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, ItalyPHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, ItalyPatrick Allaert
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICKonstantin Kudryashov
 

What's hot (20)

Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome Town
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and Hobgoblins
 
Perl Web Client
Perl Web ClientPerl Web Client
Perl Web Client
 
循環参照のはなし
循環参照のはなし循環参照のはなし
循環参照のはなし
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
 
Nubilus Perl
Nubilus PerlNubilus Perl
Nubilus Perl
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL Iterators
 
Debugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 VersionDebugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 Version
 
Things I Believe Now That I'm Old
Things I Believe Now That I'm OldThings I Believe Now That I'm Old
Things I Believe Now That I'm Old
 
Xlab #1: Advantages of functional programming in Java 8
Xlab #1: Advantages of functional programming in Java 8Xlab #1: Advantages of functional programming in Java 8
Xlab #1: Advantages of functional programming in Java 8
 
Teaching Your Machine To Find Fraudsters
Teaching Your Machine To Find FraudstersTeaching Your Machine To Find Fraudsters
Teaching Your Machine To Find Fraudsters
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design Patterns
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
 
Introdução ao Perl 6
Introdução ao Perl 6Introdução ao Perl 6
Introdução ao Perl 6
 
PHP tips and tricks
PHP tips and tricks PHP tips and tricks
PHP tips and tricks
 
Crafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::ExporterCrafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::Exporter
 
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, ItalyPHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
 
Inc
IncInc
Inc
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 

Similar to You Got Async in my PHP!

WordPress Security - WordCamp Phoenix
WordPress Security - WordCamp PhoenixWordPress Security - WordCamp Phoenix
WordPress Security - WordCamp PhoenixMark Jaquith
 
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011Alessandro Nadalin
 
Php on the desktop and php gtk2
Php on the desktop and php gtk2Php on the desktop and php gtk2
Php on the desktop and php gtk2Elizabeth Smith
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in actionJace Ju
 
The Art of Transduction
The Art of TransductionThe Art of Transduction
The Art of TransductionDavid Stockton
 
Grok Drupal (7) Theming
Grok Drupal (7) ThemingGrok Drupal (7) Theming
Grok Drupal (7) ThemingPINGV
 
CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11Combell NV
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐいHisateru Tanaka
 
Php tips-and-tricks4128
Php tips-and-tricks4128Php tips-and-tricks4128
Php tips-and-tricks4128PrinceGuru MS
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11Michelangelo van Dam
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxMichelangelo van Dam
 
Twig, the flexible, fast, and secure template language for PHP
Twig, the flexible, fast, and secure template language for PHPTwig, the flexible, fast, and secure template language for PHP
Twig, the flexible, fast, and secure template language for PHPFabien Potencier
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Shinya Ohyanagi
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsBastian Feder
 

Similar to You Got Async in my PHP! (20)

PHPSpec BDD for PHP
PHPSpec BDD for PHPPHPSpec BDD for PHP
PHPSpec BDD for PHP
 
PHPSpec BDD Framework
PHPSpec BDD FrameworkPHPSpec BDD Framework
PHPSpec BDD Framework
 
2013 - Benjamin Eberlei - Doctrine 2
2013 - Benjamin Eberlei - Doctrine 22013 - Benjamin Eberlei - Doctrine 2
2013 - Benjamin Eberlei - Doctrine 2
 
WordPress Security - WordCamp Phoenix
WordPress Security - WordCamp PhoenixWordPress Security - WordCamp Phoenix
WordPress Security - WordCamp Phoenix
 
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 
Php on the desktop and php gtk2
Php on the desktop and php gtk2Php on the desktop and php gtk2
Php on the desktop and php gtk2
 
PHP Tutorial (funtion)
PHP Tutorial (funtion)PHP Tutorial (funtion)
PHP Tutorial (funtion)
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
 
Blog Hacks 2011
Blog Hacks 2011Blog Hacks 2011
Blog Hacks 2011
 
The Art of Transduction
The Art of TransductionThe Art of Transduction
The Art of Transduction
 
Intermediate PHP
Intermediate PHPIntermediate PHP
Intermediate PHP
 
Grok Drupal (7) Theming
Grok Drupal (7) ThemingGrok Drupal (7) Theming
Grok Drupal (7) Theming
 
CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
Php tips-and-tricks4128
Php tips-and-tricks4128Php tips-and-tricks4128
Php tips-and-tricks4128
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Twig, the flexible, fast, and secure template language for PHP
Twig, the flexible, fast, and secure template language for PHPTwig, the flexible, fast, and secure template language for PHP
Twig, the flexible, fast, and secure template language for PHP
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown Parts
 

More from Chris Tankersley

Docker is Dead: Long Live Containers
Docker is Dead: Long Live ContainersDocker is Dead: Long Live Containers
Docker is Dead: Long Live ContainersChris Tankersley
 
Bend time to your will with git
Bend time to your will with gitBend time to your will with git
Bend time to your will with gitChris Tankersley
 
Using PHP Functions! (Not those functions, Google Cloud Functions)
Using PHP Functions! (Not those functions, Google Cloud Functions)Using PHP Functions! (Not those functions, Google Cloud Functions)
Using PHP Functions! (Not those functions, Google Cloud Functions)Chris Tankersley
 
Dead Simple APIs with OpenAPI
Dead Simple APIs with OpenAPIDead Simple APIs with OpenAPI
Dead Simple APIs with OpenAPIChris Tankersley
 
Killer Docker Workflows for Development
Killer Docker Workflows for DevelopmentKiller Docker Workflows for Development
Killer Docker Workflows for DevelopmentChris Tankersley
 
Docker for Developers - PHP Detroit 2018
Docker for Developers - PHP Detroit 2018Docker for Developers - PHP Detroit 2018
Docker for Developers - PHP Detroit 2018Chris Tankersley
 
BASHing at the CLI - Midwest PHP 2018
BASHing at the CLI - Midwest PHP 2018BASHing at the CLI - Midwest PHP 2018
BASHing at the CLI - Midwest PHP 2018Chris Tankersley
 
You Were Lied To About Optimization
You Were Lied To About OptimizationYou Were Lied To About Optimization
You Were Lied To About OptimizationChris Tankersley
 
Docker for PHP Developers - php[world] 2017
Docker for PHP Developers - php[world] 2017Docker for PHP Developers - php[world] 2017
Docker for PHP Developers - php[world] 2017Chris Tankersley
 
Docker for PHP Developers - Madison PHP 2017
Docker for PHP Developers - Madison PHP 2017Docker for PHP Developers - Madison PHP 2017
Docker for PHP Developers - Madison PHP 2017Chris Tankersley
 
Docker for Developers - php[tek] 2017
Docker for Developers - php[tek] 2017Docker for Developers - php[tek] 2017
Docker for Developers - php[tek] 2017Chris Tankersley
 
Why Docker? Dayton PHP, April 2017
Why Docker? Dayton PHP, April 2017Why Docker? Dayton PHP, April 2017
Why Docker? Dayton PHP, April 2017Chris Tankersley
 
OOP Is More Then Cars and Dogs - Midwest PHP 2017
OOP Is More Then Cars and Dogs - Midwest PHP 2017OOP Is More Then Cars and Dogs - Midwest PHP 2017
OOP Is More Then Cars and Dogs - Midwest PHP 2017Chris Tankersley
 
From Docker to Production - SunshinePHP 2017
From Docker to Production - SunshinePHP 2017From Docker to Production - SunshinePHP 2017
From Docker to Production - SunshinePHP 2017Chris Tankersley
 
Docker for Developers - Sunshine PHP
Docker for Developers - Sunshine PHPDocker for Developers - Sunshine PHP
Docker for Developers - Sunshine PHPChris Tankersley
 
Coming to Terms with OOP In Drupal - php[world] 2016
Coming to Terms with OOP In Drupal - php[world] 2016Coming to Terms with OOP In Drupal - php[world] 2016
Coming to Terms with OOP In Drupal - php[world] 2016Chris Tankersley
 
How We Got Here: A Brief History of Open Source
How We Got Here: A Brief History of Open SourceHow We Got Here: A Brief History of Open Source
How We Got Here: A Brief History of Open SourceChris Tankersley
 
Docker for PHP Developers - ZendCon 2016
Docker for PHP Developers - ZendCon 2016Docker for PHP Developers - ZendCon 2016
Docker for PHP Developers - ZendCon 2016Chris Tankersley
 

More from Chris Tankersley (20)

Docker is Dead: Long Live Containers
Docker is Dead: Long Live ContainersDocker is Dead: Long Live Containers
Docker is Dead: Long Live Containers
 
Bend time to your will with git
Bend time to your will with gitBend time to your will with git
Bend time to your will with git
 
Using PHP Functions! (Not those functions, Google Cloud Functions)
Using PHP Functions! (Not those functions, Google Cloud Functions)Using PHP Functions! (Not those functions, Google Cloud Functions)
Using PHP Functions! (Not those functions, Google Cloud Functions)
 
Dead Simple APIs with OpenAPI
Dead Simple APIs with OpenAPIDead Simple APIs with OpenAPI
Dead Simple APIs with OpenAPI
 
Killer Docker Workflows for Development
Killer Docker Workflows for DevelopmentKiller Docker Workflows for Development
Killer Docker Workflows for Development
 
Docker for Developers - PHP Detroit 2018
Docker for Developers - PHP Detroit 2018Docker for Developers - PHP Detroit 2018
Docker for Developers - PHP Detroit 2018
 
Docker for Developers
Docker for DevelopersDocker for Developers
Docker for Developers
 
They are Watching You
They are Watching YouThey are Watching You
They are Watching You
 
BASHing at the CLI - Midwest PHP 2018
BASHing at the CLI - Midwest PHP 2018BASHing at the CLI - Midwest PHP 2018
BASHing at the CLI - Midwest PHP 2018
 
You Were Lied To About Optimization
You Were Lied To About OptimizationYou Were Lied To About Optimization
You Were Lied To About Optimization
 
Docker for PHP Developers - php[world] 2017
Docker for PHP Developers - php[world] 2017Docker for PHP Developers - php[world] 2017
Docker for PHP Developers - php[world] 2017
 
Docker for PHP Developers - Madison PHP 2017
Docker for PHP Developers - Madison PHP 2017Docker for PHP Developers - Madison PHP 2017
Docker for PHP Developers - Madison PHP 2017
 
Docker for Developers - php[tek] 2017
Docker for Developers - php[tek] 2017Docker for Developers - php[tek] 2017
Docker for Developers - php[tek] 2017
 
Why Docker? Dayton PHP, April 2017
Why Docker? Dayton PHP, April 2017Why Docker? Dayton PHP, April 2017
Why Docker? Dayton PHP, April 2017
 
OOP Is More Then Cars and Dogs - Midwest PHP 2017
OOP Is More Then Cars and Dogs - Midwest PHP 2017OOP Is More Then Cars and Dogs - Midwest PHP 2017
OOP Is More Then Cars and Dogs - Midwest PHP 2017
 
From Docker to Production - SunshinePHP 2017
From Docker to Production - SunshinePHP 2017From Docker to Production - SunshinePHP 2017
From Docker to Production - SunshinePHP 2017
 
Docker for Developers - Sunshine PHP
Docker for Developers - Sunshine PHPDocker for Developers - Sunshine PHP
Docker for Developers - Sunshine PHP
 
Coming to Terms with OOP In Drupal - php[world] 2016
Coming to Terms with OOP In Drupal - php[world] 2016Coming to Terms with OOP In Drupal - php[world] 2016
Coming to Terms with OOP In Drupal - php[world] 2016
 
How We Got Here: A Brief History of Open Source
How We Got Here: A Brief History of Open SourceHow We Got Here: A Brief History of Open Source
How We Got Here: A Brief History of Open Source
 
Docker for PHP Developers - ZendCon 2016
Docker for PHP Developers - ZendCon 2016Docker for PHP Developers - ZendCon 2016
Docker for PHP Developers - ZendCon 2016
 

Recently uploaded

My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsSnow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsHyundai Motor Group
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxnull - The Open Security Community
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your BudgetHyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your BudgetEnjoy Anytime
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
Next-generation AAM aircraft unveiled by Supernal, S-A2
Next-generation AAM aircraft unveiled by Supernal, S-A2Next-generation AAM aircraft unveiled by Supernal, S-A2
Next-generation AAM aircraft unveiled by Supernal, S-A2Hyundai Motor Group
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 

Recently uploaded (20)

My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsSnow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your BudgetHyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
The transition to renewables in India.pdf
The transition to renewables in India.pdfThe transition to renewables in India.pdf
The transition to renewables in India.pdf
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
Next-generation AAM aircraft unveiled by Supernal, S-A2
Next-generation AAM aircraft unveiled by Supernal, S-A2Next-generation AAM aircraft unveiled by Supernal, S-A2
Next-generation AAM aircraft unveiled by Supernal, S-A2
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 

You Got Async in my PHP!

  • 1. You Got Async in my PHP! PRESENTED BY: Chris Tankersley Senior PHP Developer Advocate @dragonmantank
  • 4. Procedural Programming 4 Do this, then this, then this $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]);
  • 5. Procedural Programming • Single Threaded • Very susceptible to blocking operations • Easy to write 5 Make Twitter Object Make HTTP Object Get Tweets Read Template Render Template
  • 6. 6 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack
  • 7. 7 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main()
  • 8. 8 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new HttpClient()
  • 9. 9 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new HttpClient() require_once 'src/HttpClient.php'
  • 10. 10 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new HttpClient()
  • 11. 11 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new Twitter();
  • 12. 12 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new Twitter(); require_once 'src/Twitter.php'
  • 13. 13 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new Twitter(); require_once 'src/Twitter.php' getenv('TWITTER_KEY')
  • 14. 14 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new Twitter(); require_once 'src/Twitter.php'
  • 15. 15 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new Twitter(); require_once 'src/Twitter.php' getenv('TWITTER_SECRET')
  • 16. 16 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new Twitter(); require_once 'src/Twitter.php'
  • 17. 17 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new Twitter();
  • 18. 18 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main()
  • 19. 19 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() $t->getTweets()
  • 20. 20 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() $t->getTweets() $httpClient->get($url)
  • 21. 21 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() $t->getTweets()
  • 22. 22 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main()
  • 23. 23 Wait, how does PHP avoid blocking?
  • 24. 24 Wait, how does PHP avoid blocking? Web Servers, like Apache, are multi-threaded PHP-FPM spins up multiple threads for use
  • 25. Parallel Computing Do this, this, and this at the same time $reports = [ new DailyBalance(), new EndOfDay(), new ProfitLossUpdate(), ]; foreach ($reports as $r) { $pid = pcntl_fork(); if ($pid === 0) { $r->run(); exit(); } } 25
  • 26. Parallel Programming • Multiple Threads • Lets the OS/CPU handle scheduling • Can be tricky to write 26 Make Report Objects Run Daily Balance Report Run End of Day Report Run Profit-Loss Report End
  • 31. 31 Main Thread main() foreach($report) pcntl_fork() Daily Balance Thread main() if ($pid > 0) if ($pid > 0)
  • 33. 33 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run()
  • 34. 34 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run()pcntl_fork() End Of Day Thread main()
  • 35. 35 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run()pcntl_fork() End Of Day Thread main() if ($pid > 0) if ($pid > 0)
  • 36. 36 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run()pcntl_fork() End Of Day Thread main() if ($pid > 0) $r->run()
  • 37. 37 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run() End Of Day Thread main() if ($pid > 0) $r->run()
  • 38. 38 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run() End Of Day Thread main() if ($pid > 0) $r->run()pcntl_fork()
  • 39. 39 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run() End Of Day Thread main() if ($pid > 0) $r->run()pcntl_fork() Profit/Loss Thread main()
  • 40. 40 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run() End Of Day Thread main() if ($pid > 0) pcntl_fork() Profit/Loss Thread main() if ($pid > 0) if ($pid > 0)
  • 41. 41 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run() End Of Day Thread main() pcntl_fork() Profit/Loss Thread main() if ($pid > 0) $r->run()
  • 42. 42 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run() Profit/Loss Thread main() if ($pid > 0) $r->run()
  • 43. 43 Main Thread main() Daily Balance Thread main() if ($pid > 0) $r->run() Profit/Loss Thread main() if ($pid > 0) $r->run()
  • 44. 44 Main Thread main() Daily Balance Thread main() if ($pid > 0) $r->run() Profit/Loss Thread main() if ($pid > 0) $r->run() pcntl_wait()
  • 45. 45 Main Thread main() Daily Balance Thread main() if ($pid > 0) $r->run() Profit/Loss Thread main() if ($pid > 0) $r->run() pcntl_wait()
  • 46. 46 Main Thread main() Daily Balance Thread main() if ($pid > 0) $r->run() Profit/Loss Thread main() if ($pid > 0)pcntl_wait()
  • 47. 47 Main Thread main() Daily Balance Thread main() if ($pid > 0) $r->run() Profit/Loss Thread main() pcntl_wait()
  • 48. 48 Main Thread main() Daily Balance Thread main() if ($pid > 0) $r->run() Profit/Loss Thread pcntl_wait()
  • 49. 49 Main Thread main() Daily Balance Thread main() if ($pid > 0) $r->run() pcntl_wait()
  • 50. Async Programming Try and do this, this, and this, as simultaneously as possible $loop = EventLoop::create(); $loop->addEvent(function () { echo "Function 1" . PHP_EOL; return rand(1,10); }, function($num) { echo "Square: " . ($num * $num) . PHP_EOL; }); $loop->addEvent(function () { echo "Function 2". PHP_EOL; }, function() { echo "Function 4" . PHP_EOL; }); $loop->run(); 50
  • 51. Async Programming • Single Threaded • Uses an event loop • Allows quick executions between larger blocking operations 51 Event loop ends Queue Empty? Execute job Has callback? Add to queue Start Event Loop Yes Yes No No
  • 52. 52 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main()
  • 53. 53 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main()
  • 54. 54 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() EventLoop::create()
  • 55. 55 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() EventLoop::create() new EventLoop()
  • 56. 56 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() EventLoop::create() new EventLoop() $this->eventQueue = new SplQueue(); Event Queue
  • 57. 57 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() EventLoop::create() new EventLoop() Event Queue
  • 58. 58 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() EventLoop::create() Event Queue
  • 59. 59 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() Event Queue
  • 60. 60 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() Event Queue
  • 61. 61 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() addEvent($event1, $callback1) Event Queue
  • 62. 62 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() addEvent($event1, $callback1) $this->eventQueue->enqueue([ $event1, $callback1 ]); Event Queue $event1
  • 63. 63 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() addEvent($event1, $callback1) Event Queue $event1
  • 64. 64 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() Event Queue $event1
  • 65. 65 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() Event Queue $event1
  • 66. 66 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() addEvent($event2, $callback2) Event Queue $event1
  • 67. 67 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() addEvent($event2, $callback2) $this->eventQueue->enqueue([ $event2, $callback2 ]); Event Queue $event1 $event2
  • 68. 68 $loop = EventLoop::create(); $loop->addEvent($event1, $callback2); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() addEvent($event2, $callback2) Event Queue $event1 $event2
  • 69. 69 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() Event Queue $event1 $event2
  • 70. 70 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() Event Queue $event1 $event2
  • 71. 71 Call Stack main() run() $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Event Queue $event1 $event2
  • 72. 72 Call Stack main() run() foreach ($this->eventQueue as $event) $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php echo "Function 1" . PHP_EOL; return rand(1,10); $event[0] Event Queue $event2
  • 73. 73 Call Stack main() run() foreach ($this->eventQueue as $event) $return = $event[0]() $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php echo "Function 1" . PHP_EOL; return rand(1,10); $event[0] Event Queue $event2
  • 74. 74 Call Stack main() run() foreach ($this->eventQueue as $event) $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php 5 $return Event Queue $event2
  • 75. 75 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) if (!is_null($event[1])) 5 $return Event Queue $event2
  • 76. 76 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) if (!is_null($event[1])) 5 $return $this->addEvent($wrappedCallback) Event Queue $event2 $callback1
  • 77. 77 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) if (!is_null($event[1])) 5 $return Event Queue $event2 $callback1
  • 78. 78 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) echo "Function 2". PHP_EOL; $event[0] Event Queue $callback1
  • 79. 79 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) echo "Function 2". PHP_EOL; $event[0] Event Queue $callback1 $return = $event[0]()
  • 80. 80 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) echo "Function 2". PHP_EOL; $event[0] Event Queue $callback1 $return = $event[0]() echo
  • 81. 81 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) echo "Function 2". PHP_EOL; $event[0] Event Queue $callback1 $return = $event[0]()
  • 82. 82 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) echo "Function 2". PHP_EOL; $event[0] Event Queue $callback1 $return = $event[0]()
  • 83. 83 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) echo "Function 2". PHP_EOL; $event[0] Event Queue $callback1 $return = $event[0]() return void
  • 84. 84 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) echo "Function 2". PHP_EOL; $event[0] Event Queue $callback1 $return = $event[0]()
  • 85. 85 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) void $return Event Queue $callback1 if (!is_null($event[1]))
  • 86. 86 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) if (!is_null($event[1])) void $return $this->addEvent($wrappedCallback) Event Queue $callback1 $callback2
  • 87. 87 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) if (!is_null($event[1])) void $return Event Queue $callback1 $callback2
  • 88. 88 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) void $return Event Queue $callback1 $callback2
  • 89. 89 Most Async is just Event Loop Programming It is a different way to structure your program
  • 90. 90 Most Async is just Event Loop Programming It is a different way to structure your program Async is not: • Concurrent • Non-Blocking • Multi-threaded • Magic
  • 91. Async can help better structure your logic 91
  • 92. Async makes you think about end results, not order of operations 92
  • 94. Event Loops Adding In The Special Sauce 94
  • 95. Async Programming 95 Event loop ends Queue Empty? Execute job Has callback? Add to queue Start Event Loop Yes Yes No No
  • 96. Async Programming 96 Event loop ends Queue Empty? Execute job Has callback? Add to queue Start Event Loop Yes Yes No No Event Loops
  • 98. 98 $loop = Factory::create(); $server = new Server(function (ServerRequestInterface $request) { return new Response( 200, array( 'Content-Type' => 'text/plain' ), "Hello worldn" ); }); $socket = new ReactSocketServer( isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop ); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; $loop->run();
  • 99. 99 $loop = Factory::create(); $server = new Server(function (ServerRequestInterface $request) { return new Response( 200, array( 'Content-Type' => 'text/plain' ), "Hello worldn" ); }); $socket = new ReactSocketServer( isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop ); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; $loop->run();
  • 100. 100 $loop = Factory::create(); $server = new Server(function (ServerRequestInterface $request) { return new Response( 200, array( 'Content-Type' => 'text/plain' ), "Hello worldn" ); }); $socket = new ReactSocketServer( isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop ); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; $loop->run();
  • 101. 101 $loop = Factory::create(); $server = new Server(function (ServerRequestInterface $request) { return new Response( 200, array( 'Content-Type' => 'text/plain' ), "Hello worldn" ); }); $socket = new ReactSocketServer( isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop ); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; $loop->run();
  • 102. 102 $loop = Factory::create(); $server = new Server(function (ServerRequestInterface $request) { return new Response( 200, array( 'Content-Type' => 'text/plain' ), "Hello worldn" ); }); $socket = new ReactSocketServer( isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop ); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; $loop->run();
  • 103. 103 $loop = Factory::create(); $server = new Server(function (ServerRequestInterface $request) { return new Response( 200, array( 'Content-Type' => 'text/plain' ), "Hello worldn" ); }); $socket = new ReactSocketServer( isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop ); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; $loop->run();
  • 105. 105 $socket = new Socket(); $ws = new WsServer($socket); $ws->setStrictSubProtocolCheck(false); $server = new App('localhost', '8080', '0.0.0.0'); $server->routes->add( 'events', new Route('/events', array('_controller' => new EventsController())) ); $server->routes->add( 'onAnswer', new Route('/onAnswer', array('_controller' => new AnswerController())) ); $server->routes->add( 'socket', new Route('/socket', array('_controller' => $ws)) ); $server->run();
  • 106. 106 $socket = new Socket(); $ws = new WsServer($socket); $ws->setStrictSubProtocolCheck(false); $server = new App('localhost', '8080', '0.0.0.0'); $server->routes->add( 'events', new Route('/events', array('_controller' => new EventsController())) ); $server->routes->add( 'onAnswer', new Route('/onAnswer', array('_controller' => new AnswerController())) ); $server->routes->add( 'socket', new Route('/socket', array('_controller' => $ws)) ); $server->run();
  • 107. 107 $socket = new Socket(); $ws = new WsServer($socket); $ws->setStrictSubProtocolCheck(false); $server = new App('localhost', '8080', '0.0.0.0'); $server->routes->add( 'events', new Route('/events', array('_controller' => new EventsController())) ); $server->routes->add( 'onAnswer', new Route('/onAnswer', array('_controller' => new AnswerController())) ); $server->routes->add( 'socket', new Route('/socket', array('_controller' => $ws)) ); $server->run();
  • 108. 108 $socket = new Socket(); $ws = new WsServer($socket); $ws->setStrictSubProtocolCheck(false); $server = new App('localhost', '8080', '0.0.0.0'); $server->routes->add( 'events', new Route('/events', array('_controller' => new EventsController())) ); $server->routes->add( 'onAnswer', new Route('/onAnswer', array('_controller' => new AnswerController())) ); $server->routes->add( 'socket', new Route('/socket', array('_controller' => $ws)) ); $server->run();
  • 109. 109 public function onMessage(RatchetConnectionInterface $from, $msg) { $event = json_decode($msg, true); if($event) { switch($event['event']) { case 'websocket:dtmf': try { $uuid = $this->calls[$from->resourceId]; $talk = $this->nexmo->calls()->get( new Call($uuid) ) ->talk(); $talk->setText('You pressed ' . $event['digit']); $talk->put(); break; } catch (Exception $e) { var_dump('Error: ' . $e->getMessage()); } break; } } else { file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY); } }
  • 110. 110 public function onMessage(RatchetConnectionInterface $from, $msg) { $event = json_decode($msg, true); if($event) { switch($event['event']) { case 'websocket:dtmf': try { $uuid = $this->calls[$from->resourceId]; $talk = $this->nexmo->calls()->get( new Call($uuid) ) ->talk(); $talk->setText('You pressed ' . $event['digit']); $talk->put(); break; } catch (Exception $e) { var_dump('Error: ' . $e->getMessage()); } break; } } else { file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY); } }
  • 111. 111 public function onMessage(RatchetConnectionInterface $from, $msg) { $event = json_decode($msg, true); if($event) { switch($event['event']) { case 'websocket:dtmf': try { $uuid = $this->calls[$from->resourceId]; $talk = $this->nexmo->calls()->get( new Call($uuid) ) ->talk(); $talk->setText('You pressed ' . $event['digit']); $talk->put(); break; } catch (Exception $e) { var_dump('Error: ' . $e->getMessage()); } break; } } else { file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY); } }
  • 112. 112 public function onMessage(RatchetConnectionInterface $from, $msg) { $event = json_decode($msg, true); if($event) { switch($event['event']) { case 'websocket:dtmf': try { $uuid = $this->calls[$from->resourceId]; $talk = $this->nexmo->calls()->get( new Call($uuid) ) ->talk(); $talk->setText('You pressed ' . $event['digit']); $talk->put(); break; } catch (Exception $e) { var_dump('Error: ' . $e->getMessage()); } break; } } else { file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY); } }
  • 113. 113 public function onMessage(RatchetConnectionInterface $from, $msg) { $event = json_decode($msg, true); if($event) { switch($event['event']) { case 'websocket:dtmf': try { $uuid = $this->calls[$from->resourceId]; $talk = $this->nexmo->calls()->get( new Call($uuid) ) ->talk(); $talk->setText('You pressed ' . $event['digit']); $talk->put(); break; } catch (Exception $e) { var_dump('Error: ' . $e->getMessage()); } break; } } else { file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY); } }
  • 114. 114 public function onMessage(RatchetConnectionInterface $from, $msg) { $event = json_decode($msg, true); if($event) { switch($event['event']) { case 'websocket:dtmf': try { $uuid = $this->calls[$from->resourceId]; $talk = $this->nexmo->calls()->get( new Call($uuid) ) ->talk(); $talk->setText('You pressed ' . $event['digit']); $talk->put(); break; } catch (Exception $e) { var_dump('Error: ' . $e->getMessage()); } break; } } else { file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY); } }
  • 117. Callbacks Being Passed To More Callbacks $activeFloridaUsers = array_filter( array_filter( array_filter($users, function($user) { return $user->accountActive(); }, function($user) { return $user->getBalance() > 0; }), function($user) { return $user->getState() === "FL"; } )); 117
  • 118. Callbacks Being Passed To More Callbacks $activeFloridaUsers = array_filter( array_filter( array_filter($users, function($user) { return $user->accountActive(); }, function($user) { return $user->getBalance() > 0; }), function($user) { return $user->getState() === "FL"; } )); 118
  • 119. Callbacks Being Passed To More Callbacks $activeFloridaUsers = array_filter( array_filter( array_filter($users, function($user) { return $user->accountActive(); }, function($user) { return $user->getBalance() > 0; }), function($user) { return $user->getState() === "FL"; } )); 119
  • 120. Callbacks Being Passed To More Callbacks $activeFloridaUsers = array_filter( array_filter( array_filter($users, function($user) { return $user->accountActive(); }, function($user) { return $user->getBalance() > 0; }), function($user) { return $user->getState() === "FL"; } )); 120
  • 121. Callbacks Being Passed To More Callbacks $activeFloridaUsers = array_filter( array_filter( array_filter($users, function($user) { return $user->accountActive(); }), function($user) { return $user->getBalance() > 0; }), function($user) { return $user->getState() === "FL"; } )); 121
  • 122. Callbacks Being Passed To More Callbacks $activeFloridaUsers = array_filter( array_filter( array_filter($users, function($user) { return $user->accountActive(); }), function($user) { return $user->getBalance() > 0; }), function($user) { return $user->getState() === "FL"; } )); 122
  • 123. What do Promises provide? 123 • Built off of Promises/A+ • A cleaner interface for callbacks • A more structured workflow for one logic block to the next • A way to handle errors in a clean manner
  • 124. A Cleaner Callback Interface use GuzzleHttpPromisePromise; $fulfilled = function ($value) { echo 'The promise was fulfilled.'; }; $rejected = function ($reason) { echo 'The promise was rejected.'; }; $promise = new Promise(); $promise->then($fulfilled, $rejected); $promise->resolve(); 124
  • 125. A Cleaner Callback Interface use GuzzleHttpPromisePromise; $fulfilled = function ($value) { echo 'The promise was fulfilled.'; }; $rejected = function ($reason) { echo 'The promise was rejected.'; }; $promise = new Promise(); $promise->then($fulfilled, $rejected); $promise->resolve(); 125
  • 126. A Cleaner Callback Interface use GuzzleHttpPromisePromise; $fulfilled = function ($value) { echo 'The promise was fulfilled.'; }; $rejected = function ($reason) { echo 'The promise was rejected.'; }; $promise = new Promise(); $promise->then($fulfilled, $rejected); $promise->resolve(); 126
  • 127. A Cleaner Callback Interface use GuzzleHttpPromisePromise; $fulfilled = function ($value) { echo 'The promise was fulfilled.'; }; $rejected = function ($reason) { echo 'The promise was rejected.'; }; $promise = new Promise(); $promise->then($fulfilled, $rejected); $promise->resolve(); 127
  • 128. A Cleaner Callback Interface use GuzzleHttpPromisePromise; $fulfilled = function ($value) { echo 'The promise was fulfilled.'; }; $rejected = function ($reason) { echo 'The promise was rejected.'; }; $promise = new Promise(); $promise->then($fulfilled, $rejected); $promise->then($fulfilled2, $rejected2); $promise->resolve(); 128
  • 129. $promise = new Promise(); $promise->then(function ($users) { return array_filter($users, function($user) { return $user->accountActive(); }); }); $promise->then(function ($activeUsers) { return array_filter($activeUsers, function($user) { return $user->getBalance() > 0; }); }); $promise->then(function ($usersWithBalance) { return array_filter($usersWithBalance, function($user) { return $user->getState() === 'FL'; }); }); 129
  • 130. $promise = new Promise(); $promise->then(function ($users) { return array_filter($users, function($user) { return $user->accountActive(); }); }); $promise->then(function ($activeUsers) { return array_filter($activeUsers, function($user) { return $user->getBalance() > 0; }); }); $promise->then(function ($usersWithBalance) { return array_filter($usersWithBalance, function($user) { return $user->getState() === 'FL'; }); }); 130
  • 131. $promise = new Promise(); $promise->then(function ($users) { return array_filter($users, function($user) { return $user->accountActive(); }); }); $promise->then(function ($activeUsers) { return array_filter($activeUsers, function($user) { return $user->getBalance() > 0; }); }); $promise->then(function ($usersWithBalance) { return array_filter($usersWithBalance, function($user) { return $user->getState() === 'FL'; }); }); 131
  • 132. $promise = new Promise(); $promise->then(function ($users) { return array_filter($users, function($user) { return $user->accountActive(); }); }); $promise->then(function ($activeUsers) { return array_filter($activeUsers, function($user) { return $user->getBalance() > 0; }); }); $promise->then(function ($usersWithBalance) { return array_filter($usersWithBalance, function($user) { return $user->getState() === 'FL'; }); }); 132
  • 133. $promise = new Promise(); $promise->then(function ($users) { return array_filter($users, function($user) { return $user->accountActive(); }); }); $promise->then(function ($activeUsers) { return array_filter($activeUsers, function($user) { return $user->getBalance() > 0; }); }); $promise->then(function ($usersWithBalance) { return array_filter($usersWithBalance, function($user) { return $user->getState() === 'FL'; }); }); 133
  • 138. VONAGE CONFIDENTIAL Generators and Coroutines yielding Control Back to the Event Loop 138
  • 139. Swoole Like PHP-FPM but has coroutines 139
  • 140. 140 Chris Tankersley Senior PHP Developer Advocate at Nexmo @dragonmantank chris@ctankersley.com