SlideShare a Scribd company logo
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
Ad

More Related Content

What's hot (20)

Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome Town
Ross 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 Hobgoblins
Ross Tuck
 
Perl Web Client
Perl Web ClientPerl Web Client
Perl Web Client
Flavio Poletti
 
循環参照のはなし
循環参照のはなし循環参照のはなし
循環参照のはなし
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 Pimple
Hugo Hamon
 
Nubilus Perl
Nubilus PerlNubilus Perl
Nubilus Perl
Flavio Poletti
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL Iterators
Mark 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 Version
Ian 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 Old
Ross 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 8
XSolve
 
Teaching Your Machine To Find Fraudsters
Teaching Your Machine To Find FraudstersTeaching Your Machine To Find Fraudsters
Teaching Your Machine To Find Fraudsters
Ian 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 / XSolve
XSolve
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design Patterns
Hugo Hamon
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
Hugo Hamon
 
Introdução ao Perl 6
Introdução ao Perl 6Introdução ao Perl 6
Introdução ao Perl 6
garux
 
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::Exporter
Ricardo 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, Italy
Patrick Allaert
 
Inc
IncInc
Inc
Lax Sindikat
 
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
Konstantin Kudryashov
 
Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome Town
Ross 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 Hobgoblins
Ross 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 Pimple
Hugo Hamon
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL Iterators
Mark 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 Version
Ian 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 Old
Ross 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 8
XSolve
 
Teaching Your Machine To Find Fraudsters
Teaching Your Machine To Find FraudstersTeaching Your Machine To Find Fraudsters
Teaching Your Machine To Find Fraudsters
Ian 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 / XSolve
XSolve
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design Patterns
Hugo Hamon
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
Hugo Hamon
 
Introdução ao Perl 6
Introdução ao Perl 6Introdução ao Perl 6
Introdução ao Perl 6
garux
 
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::Exporter
Ricardo 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, Italy
Patrick 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 DIC
Konstantin Kudryashov
 

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

PHPSpec BDD for PHP
PHPSpec BDD for PHPPHPSpec BDD for PHP
PHPSpec BDD for PHP
Marcello Duarte
 
PHPSpec BDD Framework
PHPSpec BDD FrameworkPHPSpec BDD Framework
PHPSpec BDD Framework
Marcello Duarte
 
2013 - Benjamin Eberlei - Doctrine 2
2013 - Benjamin Eberlei - Doctrine 22013 - Benjamin Eberlei - Doctrine 2
2013 - Benjamin Eberlei - Doctrine 2
PHP Conference Argentina
 
WordPress Security - WordCamp Phoenix
WordPress Security - WordCamp PhoenixWordPress Security - WordCamp Phoenix
WordPress Security - WordCamp Phoenix
Mark 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-2011
Alessandro 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 gtk2
Elizabeth Smith
 
PHP Tutorial (funtion)
PHP Tutorial (funtion)PHP Tutorial (funtion)
PHP Tutorial (funtion)
Tinnakorn Puttha
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
Jace Ju
 
Blog Hacks 2011
Blog Hacks 2011Blog Hacks 2011
Blog Hacks 2011
Yusuke Wada
 
The Art of Transduction
The Art of TransductionThe Art of Transduction
The Art of Transduction
David Stockton
 
Intermediate PHP
Intermediate PHPIntermediate PHP
Intermediate PHP
Bradley Holt
 
Grok Drupal (7) Theming
Grok Drupal (7) ThemingGrok Drupal (7) Theming
Grok Drupal (7) Theming
PINGV
 
CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11
Combell 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-tricks4128
PrinceGuru MS
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
Michelangelo van Dam
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
Michelangelo 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 PHP
Fabien Potencier
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2
Shinya Ohyanagi
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown Parts
Bastian Feder
 
WordPress Security - WordCamp Phoenix
WordPress Security - WordCamp PhoenixWordPress Security - WordCamp Phoenix
WordPress Security - WordCamp Phoenix
Mark 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-2011
Alessandro 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 gtk2
Elizabeth Smith
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
Jace Ju
 
The Art of Transduction
The Art of TransductionThe Art of Transduction
The Art of Transduction
David Stockton
 
Grok Drupal (7) Theming
Grok Drupal (7) ThemingGrok Drupal (7) Theming
Grok Drupal (7) Theming
PINGV
 
CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11
Combell 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-tricks4128
PrinceGuru MS
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
Michelangelo van Dam
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
Michelangelo 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 PHP
Fabien Potencier
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2
Shinya Ohyanagi
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown Parts
Bastian Feder
 
Ad

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
Chris 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 git
Chris 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 OpenAPI
Chris Tankersley
 
Killer Docker Workflows for Development
Killer Docker Workflows for DevelopmentKiller Docker Workflows for Development
Killer Docker Workflows for Development
Chris Tankersley
 
Docker for Developers - PHP Detroit 2018
Docker for Developers - PHP Detroit 2018Docker for Developers - PHP Detroit 2018
Docker for Developers - PHP Detroit 2018
Chris Tankersley
 
Docker for Developers
Docker for DevelopersDocker for Developers
Docker for Developers
Chris Tankersley
 
They are Watching You
They are Watching YouThey are Watching You
They are Watching You
Chris 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 2018
Chris Tankersley
 
You Were Lied To About Optimization
You Were Lied To About OptimizationYou Were Lied To About Optimization
You Were Lied To About Optimization
Chris 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] 2017
Chris 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 2017
Chris Tankersley
 
Docker for Developers - php[tek] 2017
Docker for Developers - php[tek] 2017Docker for Developers - php[tek] 2017
Docker for Developers - php[tek] 2017
Chris Tankersley
 
Why Docker? Dayton PHP, April 2017
Why Docker? Dayton PHP, April 2017Why Docker? Dayton PHP, April 2017
Why Docker? Dayton PHP, April 2017
Chris 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 2017
Chris Tankersley
 
From Docker to Production - SunshinePHP 2017
From Docker to Production - SunshinePHP 2017From Docker to Production - SunshinePHP 2017
From Docker to Production - SunshinePHP 2017
Chris Tankersley
 
Docker for Developers - Sunshine PHP
Docker for Developers - Sunshine PHPDocker for Developers - Sunshine PHP
Docker for Developers - Sunshine PHP
Chris 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] 2016
Chris 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 Source
Chris Tankersley
 
Docker for PHP Developers - ZendCon 2016
Docker for PHP Developers - ZendCon 2016Docker for PHP Developers - ZendCon 2016
Docker for PHP Developers - ZendCon 2016
Chris Tankersley
 
Docker is Dead: Long Live Containers
Docker is Dead: Long Live ContainersDocker is Dead: Long Live Containers
Docker is Dead: Long Live Containers
Chris 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 git
Chris 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 OpenAPI
Chris Tankersley
 
Killer Docker Workflows for Development
Killer Docker Workflows for DevelopmentKiller Docker Workflows for Development
Killer Docker Workflows for Development
Chris Tankersley
 
Docker for Developers - PHP Detroit 2018
Docker for Developers - PHP Detroit 2018Docker for Developers - PHP Detroit 2018
Docker for Developers - PHP Detroit 2018
Chris 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 2018
Chris Tankersley
 
You Were Lied To About Optimization
You Were Lied To About OptimizationYou Were Lied To About Optimization
You Were Lied To About Optimization
Chris 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] 2017
Chris 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 2017
Chris Tankersley
 
Docker for Developers - php[tek] 2017
Docker for Developers - php[tek] 2017Docker for Developers - php[tek] 2017
Docker for Developers - php[tek] 2017
Chris Tankersley
 
Why Docker? Dayton PHP, April 2017
Why Docker? Dayton PHP, April 2017Why Docker? Dayton PHP, April 2017
Why Docker? Dayton PHP, April 2017
Chris 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 2017
Chris Tankersley
 
From Docker to Production - SunshinePHP 2017
From Docker to Production - SunshinePHP 2017From Docker to Production - SunshinePHP 2017
From Docker to Production - SunshinePHP 2017
Chris Tankersley
 
Docker for Developers - Sunshine PHP
Docker for Developers - Sunshine PHPDocker for Developers - Sunshine PHP
Docker for Developers - Sunshine PHP
Chris 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] 2016
Chris 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 Source
Chris Tankersley
 
Docker for PHP Developers - ZendCon 2016
Docker for PHP Developers - ZendCon 2016Docker for PHP Developers - ZendCon 2016
Docker for PHP Developers - ZendCon 2016
Chris Tankersley
 
Ad

Recently uploaded (20)

Andrew Marnell: Transforming Business Strategy Through Data-Driven Insights
Andrew Marnell: Transforming Business Strategy Through Data-Driven InsightsAndrew Marnell: Transforming Business Strategy Through Data-Driven Insights
Andrew Marnell: Transforming Business Strategy Through Data-Driven Insights
Andrew Marnell
 
Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)
Ortus Solutions, Corp
 
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath MaestroDev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
UiPathCommunity
 
tecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdftecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdf
fjgm517
 
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul
 
Procurement Insights Cost To Value Guide.pptx
Procurement Insights Cost To Value Guide.pptxProcurement Insights Cost To Value Guide.pptx
Procurement Insights Cost To Value Guide.pptx
Jon Hansen
 
Electronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploitElectronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploit
niftliyevhuseyn
 
HCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser EnvironmentsHCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser Environments
panagenda
 
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
Alan Dix
 
Heap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and DeletionHeap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and Deletion
Jaydeep Kale
 
How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?
Daniel Lehner
 
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptxDevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
Justin Reock
 
2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx
Samuele Fogagnolo
 
Big Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur MorganBig Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur Morgan
Arthur Morgan
 
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdfComplete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Software Company
 
AI and Data Privacy in 2025: Global Trends
AI and Data Privacy in 2025: Global TrendsAI and Data Privacy in 2025: Global Trends
AI and Data Privacy in 2025: Global Trends
InData Labs
 
Rusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond SparkRusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond Spark
carlyakerly1
 
Linux Support for SMARC: How Toradex Empowers Embedded Developers
Linux Support for SMARC: How Toradex Empowers Embedded DevelopersLinux Support for SMARC: How Toradex Empowers Embedded Developers
Linux Support for SMARC: How Toradex Empowers Embedded Developers
Toradex
 
Technology Trends in 2025: AI and Big Data Analytics
Technology Trends in 2025: AI and Big Data AnalyticsTechnology Trends in 2025: AI and Big Data Analytics
Technology Trends in 2025: AI and Big Data Analytics
InData Labs
 
Splunk Security Update | Public Sector Summit Germany 2025
Splunk Security Update | Public Sector Summit Germany 2025Splunk Security Update | Public Sector Summit Germany 2025
Splunk Security Update | Public Sector Summit Germany 2025
Splunk
 
Andrew Marnell: Transforming Business Strategy Through Data-Driven Insights
Andrew Marnell: Transforming Business Strategy Through Data-Driven InsightsAndrew Marnell: Transforming Business Strategy Through Data-Driven Insights
Andrew Marnell: Transforming Business Strategy Through Data-Driven Insights
Andrew Marnell
 
Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)
Ortus Solutions, Corp
 
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath MaestroDev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
UiPathCommunity
 
tecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdftecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdf
fjgm517
 
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul
 
Procurement Insights Cost To Value Guide.pptx
Procurement Insights Cost To Value Guide.pptxProcurement Insights Cost To Value Guide.pptx
Procurement Insights Cost To Value Guide.pptx
Jon Hansen
 
Electronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploitElectronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploit
niftliyevhuseyn
 
HCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser EnvironmentsHCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser Environments
panagenda
 
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
Alan Dix
 
Heap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and DeletionHeap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and Deletion
Jaydeep Kale
 
How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?
Daniel Lehner
 
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptxDevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
Justin Reock
 
2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx
Samuele Fogagnolo
 
Big Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur MorganBig Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur Morgan
Arthur Morgan
 
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdfComplete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Software Company
 
AI and Data Privacy in 2025: Global Trends
AI and Data Privacy in 2025: Global TrendsAI and Data Privacy in 2025: Global Trends
AI and Data Privacy in 2025: Global Trends
InData Labs
 
Rusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond SparkRusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond Spark
carlyakerly1
 
Linux Support for SMARC: How Toradex Empowers Embedded Developers
Linux Support for SMARC: How Toradex Empowers Embedded DevelopersLinux Support for SMARC: How Toradex Empowers Embedded Developers
Linux Support for SMARC: How Toradex Empowers Embedded Developers
Toradex
 
Technology Trends in 2025: AI and Big Data Analytics
Technology Trends in 2025: AI and Big Data AnalyticsTechnology Trends in 2025: AI and Big Data Analytics
Technology Trends in 2025: AI and Big Data Analytics
InData Labs
 
Splunk Security Update | Public Sector Summit Germany 2025
Splunk Security Update | Public Sector Summit Germany 2025Splunk Security Update | Public Sector Summit Germany 2025
Splunk Security Update | Public Sector Summit Germany 2025
Splunk
 

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 [email protected]