php, rabbitmq, and you
DESCRIPTION
PHP, RabbitMQ, and You talk given at MidwestPHP 2014 Video of the screens can be found here http://www.youtube.com/watch?v=Nh5oFSXEg6k This includes the videos of the sample code.TRANSCRIPT
![Page 1: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/1.jpg)
PHP, RabbitMQ, and You#mwphp14 #rabbitmq @jasonlotito
MidwestPHP 2014 - RabbitMQ What will we be covering?
1. What is RabbitMQ
2. Technology Overview
3. Publishers
4. Consumers
5. Exchanges
6. Queues
7. Bindings
8. Carrot to make things easy
9. Publish events from the web
10.Multiple consumers
11.Management UI Publishing
12.Consumers Publishing
![Page 2: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/2.jpg)
PHP, RabbitMQ, and You#mwphp14 #rabbitmq @jasonlotito
![Page 3: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/3.jpg)
Jason LotitoSenior Architect @ MeetMe
@jasonlotito.com github.com/[email protected]
!
Senior Architect means people can blame me when things don’t work as expected.
When things work, it’s because they worked around my code.
![Page 4: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/4.jpg)
Who has worked with RabbitMQ in production?
Raise your hands. The only audience participation part, I promise.
![Page 5: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/5.jpg)
Part 1 Crash Course In RabbitMQ
1. What is RabbitMQ
2. Technology Overview
3. Publishers
4. Consumers
5. Exchanges
6. Queues
7. Bindings
![Page 6: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/6.jpg)
– RabbitMQ In Action*, Manning
“RabbitMQ is an open source message broker and queueing server that can be used to let
disparate applications share data via a common protocol, or to simply queue jobs for processing
by distributed workers.
”
![Page 7: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/7.jpg)
Where RabbitMQ Sits(P) Producer/Publisher - (X) Exchange - (C) Consumer
![Page 8: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/8.jpg)
Event Occurs in Application(P) Producer/Publisher - (X) Exchange - (C) Consumer
![Page 9: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/9.jpg)
Message is Sent to Exchange(P) Producer/Publisher - (X) Exchange - (C) Consumer
![Page 10: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/10.jpg)
Message is Sent to Queue(P) Producer/Publisher - (X) Exchange - (C) Consumer
Exchanges connect to Queues through Bindings
![Page 11: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/11.jpg)
Message is Sent to Consumer(P) Producer/Publisher - (X) Exchange - (C) Consumer
![Page 12: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/12.jpg)
– Me, Now
“Where as a database handles your data, a message queue handles your events.”
![Page 13: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/13.jpg)
A database handles nouns. A message queue handles verbs.
![Page 14: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/14.jpg)
But enough talkLet’s see some code!
![Page 15: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/15.jpg)
composer.json"require": { "videlalvaro/php-amqplib": "2.2.*"}
![Page 16: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/16.jpg)
We are starting with the publisher
![Page 17: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/17.jpg)
Publisher: send.php<?php// Setup, $ php send.php whatever you want to sendrequire_once 'vendor/autoload.php'; $config = require('config.php'); use PhpAmqpLib\Connection\AMQPConnection; use PhpAmqpLib\Message\AMQPMessage; // Message Prep$connection = new AMQPConnection($config['mq']['host'], $config['mq']['port'], $config['mq']['user'], $config['mq']['pass']); $channel = $connection->channel(); $message = join(' ', array_splice($argv, 1)); $message = empty($message) ? 'Hello world!' : $message; // Publish Message$channel->basic_publish(new AMQPMessage( $message ), '', 'hello'); echo " [x] Sent '$message'\n"; $channel->close(); $connection->close();
![Page 18: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/18.jpg)
Publisher: send.php<?php// Setup, $ php send.php whatever you want to sendrequire_once 'vendor/autoload.php'; $config = require('config.php'); use PhpAmqpLib\Connection\AMQPConnection; use PhpAmqpLib\Message\AMQPMessage; // Message Prep$connection = new AMQPConnection($config['mq']['host'], $config['mq']['port'], $config['mq']['user'], $config['mq']['pass']); $channel = $connection->channel(); $message = join(' ', array_splice($argv, 1)); $message = empty($message) ? 'Hello world!' : $message; // Publish Message$channel->basic_publish(new AMQPMessage( $message ), '', 'hello'); echo " [x] Sent '$message'\n"; $channel->close(); $connection->close();
![Page 19: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/19.jpg)
Publisher: send.php<?php// Setup, $ php send.php whatever you want to sendrequire_once 'vendor/autoload.php'; $config = require('config.php'); use PhpAmqpLib\Connection\AMQPConnection; use PhpAmqpLib\Message\AMQPMessage; // Message Prep$connection = new AMQPConnection($config['mq']['host'], $config['mq']['port'], $config['mq']['user'], $config['mq']['pass']); $channel = $connection->channel(); $message = join(' ', array_splice($argv, 1)); $message = empty($message) ? 'Hello world!' : $message; // Publish Message$channel->basic_publish(new AMQPMessage( $message ), '', 'hello'); echo " [x] Sent '$message'\n"; $channel->close(); $connection->close();
![Page 20: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/20.jpg)
Publisher: send.php<?php// Setup, $ php send.php whatever you want to sendrequire_once 'vendor/autoload.php'; $config = require('config.php'); use PhpAmqpLib\Connection\AMQPConnection; use PhpAmqpLib\Message\AMQPMessage; // Message Prep$connection = new AMQPConnection($config['mq']['host'], $config['mq']['port'], $config['mq']['user'], $config['mq']['pass']); $channel = $connection->channel(); $message = join(' ', array_splice($argv, 1)); $message = empty($message) ? 'Hello world!' : $message; // Publish Message$channel->basic_publish(new AMQPMessage( $message ), '', 'hello'); echo " [x] Sent '$message'\n"; $channel->close(); $connection->close();
![Page 21: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/21.jpg)
Publisher: send.php<?php// Setup, $ php send.php whatever you want to sendrequire_once 'vendor/autoload.php'; $config = require('config.php'); use PhpAmqpLib\Connection\AMQPConnection; use PhpAmqpLib\Message\AMQPMessage; // Message Prep$connection = new AMQPConnection($config['mq']['host'], $config['mq']['port'], $config['mq']['user'], $config['mq']['pass']); $channel = $connection->channel(); $message = join(' ', array_splice($argv, 1)); $message = empty($message) ? 'Hello world!' : $message; // Publish Message$channel->basic_publish(new AMQPMessage( $message ), '', 'hello'); echo " [x] Sent '$message'\n"; $channel->close(); $connection->close();
![Page 22: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/22.jpg)
Now we create a consumer
![Page 23: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/23.jpg)
Consumer: receive.php<?phprequire_once 'vendor/autoload.php'; $config = require('config.php'); use PhpAmqpLib\Connection\AMQPConnection; $connection = new AMQPConnection($config['mq']['host'], $config['mq']['port'], $config['mq']['user'], $config['mq']['pass']); $channel = $connection->channel(); $channel->queue_declare('hello', false, false, false, true); echo ' [*] Waiting for messages. To exit press CTRL+C', "\n"; $handler = function($message) use($channel){ echo sprintf('Message: %s' . PHP_EOL, $message->body); }; $channel->basic_consume('hello', false, true, true, false, false, $handler); $channel->wait();
![Page 24: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/24.jpg)
Consumer: receive.php<?phprequire_once 'vendor/autoload.php'; $config = require('config.php'); use PhpAmqpLib\Connection\AMQPConnection; $connection = new AMQPConnection($config['mq']['host'], $config['mq']['port'], $config['mq']['user'], $config['mq']['pass']); $channel = $connection->channel(); $channel->queue_declare('hello', false, false, false, true); echo ' [*] Waiting for messages. To exit press CTRL+C', "\n"; $handler = function($message) use($channel){ echo sprintf('Message: %s' . PHP_EOL, $message->body); }; $channel->basic_consume('hello', false, true, true, false, false, $handler); $channel->wait();
![Page 25: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/25.jpg)
Consumer: receive.php<?phprequire_once 'vendor/autoload.php'; $config = require('config.php'); use PhpAmqpLib\Connection\AMQPConnection; $connection = new AMQPConnection($config['mq']['host'], $config['mq']['port'], $config['mq']['user'], $config['mq']['pass']); $channel = $connection->channel(); $channel->queue_declare('hello', false, false, false, true); echo ' [*] Waiting for messages. To exit press CTRL+C', "\n"; $handler = function($message) use($channel){ echo sprintf('Message: %s' . PHP_EOL, $message->body); }; $channel->basic_consume('hello', false, true, true, false, false, $handler); $channel->wait();
![Page 26: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/26.jpg)
Consumer: receive.php<?phprequire_once 'vendor/autoload.php'; $config = require('config.php'); use PhpAmqpLib\Connection\AMQPConnection; $connection = new AMQPConnection($config['mq']['host'], $config['mq']['port'], $config['mq']['user'], $config['mq']['pass']); $channel = $connection->channel(); $channel->queue_declare('hello', false, false, false, true); echo ' [*] Waiting for messages. To exit press CTRL+C', "\n"; $handler = function($message) use($channel){ echo sprintf('Message: %s' . PHP_EOL, $message->body); }; $channel->basic_consume('hello', false, true, true, false, false, $handler); $channel->wait();
![Page 27: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/27.jpg)
![Page 28: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/28.jpg)
Message is Sent to Exchange(P) Producer/Publisher - (X) Exchange - (C) Consumer
![Page 29: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/29.jpg)
Exchange TypesDirect, Fanout, and Topic
![Page 30: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/30.jpg)
![Page 31: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/31.jpg)
![Page 32: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/32.jpg)
![Page 33: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/33.jpg)
Queue bound to many exchanges
![Page 34: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/34.jpg)
$msg = new AMQPMessage( $message ); $channel->basic_publish($msg, '', ‘messages.new');
![Page 35: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/35.jpg)
* matches one word # matches zero or more words
A word is delineated by .
*, #, and .
![Page 36: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/36.jpg)
*.new messages.*
NOT *.messages.*
messages.new matches
![Page 37: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/37.jpg)
NOT spam.* spam.*.* spam.#
spam.message.new matches
![Page 38: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/38.jpg)
Now Let’s Create an Exchange and a Queue
![Page 39: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/39.jpg)
Using the Management UIrabbitmq-plugins enable rabbitmq_management
http://localhost:15672
![Page 40: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/40.jpg)
![Page 41: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/41.jpg)
![Page 42: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/42.jpg)
We’ve Created EverythingPublishers, Exchanges, Bindings, Queues, and Consumers
![Page 43: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/43.jpg)
So what can we do with this?
![Page 44: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/44.jpg)
Part 2 PHP & RabbitMQ Together
1. Carrot to make things easy
2. Publish events from the web
3. Multiple consumers
4. Management UI Publishing
5. Consumers Publishing
![Page 46: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/46.jpg)
Carrot Consumer Code<?phprequire_once 'vendor/autoload.php'; use Carrot\Consumer; $queue = 'new_messages'; $handler = function($msg){ echo $msg, PHP_EOL; return true; }; (new Consumer())->listenTo($queue, $handler) ->listenAndWait(); !
![Page 47: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/47.jpg)
Carrot Publisher Code
<?phprequire 'vendor/autoload.php'; use Carrot\Publisher; $msg = implode(' ', array_splice($argv, 1)); (new Publisher('messages')) ->publish('message.new', $msg);
![Page 48: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/48.jpg)
![Page 49: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/49.jpg)
Make publishing easy
![Page 50: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/50.jpg)
Make consuming easier
![Page 51: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/51.jpg)
github.com/jasonlotito/midwest-rabbitmq/tree/carrot
![Page 52: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/52.jpg)
Adding the Web
![Page 53: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/53.jpg)
Publisher$publisher = new Publisher('messages'); $sendCount = (int) (isset($_POST['simulatedMessageCount']) ? $_POST['simulatedMessageCount'] : 1); for($x = 0; $x<$sendCount; $x++){ if(isset($_POST['simulateWork'])) { usleep(500000); $msg = ['comment' => $_POST['comment'] . " $x"]; $publisher->eventuallyPublish('message.new', $msg); } else { $msg = ['comment' => $_POST['comment'] . " $x"]; $publisher->publish('message.new', $msg); } }
![Page 54: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/54.jpg)
Let’s use the written Carrot Consumer Code
![Page 55: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/55.jpg)
![Page 56: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/56.jpg)
batch_basic_publishpublic function eventuallyPublish($routingKey, $message) { $msg = $this->buildMessage($message); $channel = $this->getChannel(); $channel->batch_basic_publish($msg, $this->exchange, $routingKey); $this->registerShutdownHandler(); } public function finallyPublish() { if ($this->doBatchPublish) { $this->doBatchPublish = false; $this->getChannel()->publish_batch(); } } !// register finallyPublish private function registerShutdownHandler();
![Page 57: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/57.jpg)
Publish from the web Let’s add another consumer
Without changing existing code
![Page 58: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/58.jpg)
send text messages
$queueName = 'messages_for_nexmo'; (new Consumer()) ->bind($queueName, 'messages', 'message.new') ->listenTo($queueName, function($msg) use($key, $secret, $phoneNumber) { $msg = json_decode($msg); $urlString = 'https://rest.nexmo.com/sms/json?api_key=%s&api_secret=%s' . '&from=17088568489&to=%s&text=%s'; $preparedMessage = urlencode($msg->comment); $url = sprintf($urlString, $key, $secret, $phoneNumber, $preparedMessage); $res = file_get_contents($url); $result = json_decode($res); $messageResult = $result->messages[0]; echo "Message Result: " . ($messageResult->status === '0' ? 'Message Sent' : 'Message not sent') . PHP_EOL; return $messageResult->status === '0'; })->listenAndWait();
![Page 59: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/59.jpg)
send text messages
$queueName = 'messages_for_nexmo'; (new Consumer()) ->bind($queueName, 'messages', 'message.new') ->listenTo($queueName, function($msg) use($key, $secret, $phoneNumber) { $msg = json_decode($msg); $urlString = 'https://rest.nexmo.com/sms/json?api_key=%s&api_secret=%s' . '&from=17088568489&to=%s&text=%s'; $preparedMessage = urlencode($msg->comment); $url = sprintf($urlString, $key, $secret, $phoneNumber, $preparedMessage); $res = file_get_contents($url); $result = json_decode($res); $messageResult = $result->messages[0]; echo "Message Result: " . ($messageResult->status === '0' ? 'Message Sent' : 'Message not sent') . PHP_EOL; return $messageResult->status === '0'; })->listenAndWait();
![Page 60: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/60.jpg)
send text messages
$queueName = 'messages_for_nexmo'; (new Consumer()) ->bind($queueName, 'messages', 'message.new') ->listenTo($queueName, function($msg) use($key, $secret, $phoneNumber) { $msg = json_decode($msg); $urlString = 'https://rest.nexmo.com/sms/json?api_key=%s&api_secret=%s' . '&from=17088568489&to=%s&text=%s'; $preparedMessage = urlencode($msg->comment); $url = sprintf($urlString, $key, $secret, $phoneNumber, $preparedMessage); $res = file_get_contents($url); $result = json_decode($res); $messageResult = $result->messages[0]; echo "Message Result: " . ($messageResult->status === '0' ? 'Message Sent' : 'Message not sent') . PHP_EOL; return $messageResult->status === '0'; })->listenAndWait();
![Page 61: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/61.jpg)
Both queues get the message
![Page 62: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/62.jpg)
![Page 63: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/63.jpg)
Let’s add another layer
![Page 64: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/64.jpg)
Yo dawg, let’s have a consumer publish
![Page 65: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/65.jpg)
Send an email After the text message
![Page 66: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/66.jpg)
Create a new Exchange
![Page 67: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/67.jpg)
Update text message consumer
$publisher = new Publisher('sms'); (new Consumer()) ->bind($queueName, 'messages', 'message.new') ->listenTo($queueName, function($msg) use($key, $secret, $phoneNumber, $publisher) { // existing code $successful = $messageResult->status === '0'; if ($successful) { $publisher->publish(‘sms.sent', ['message' => $msg->comment]); } return $successful; })->listenAndWait();
![Page 68: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/68.jpg)
Let’s write the email consumerAnd I’ll also show you how to easily test them
![Page 69: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/69.jpg)
Email Consumer
(new Consumer()) ->bind('send_email', 'emails', '*.send') ->bind('send_email', 'sms', '*.sent') ->listenTo('send_email', function($message){ $msg = json_decode($message); mail('[email protected]', 'MidwestPHP RabbitMQ Talk', $msg->message); echo 'Message sent: ' . $msg->message . PHP_EOL; return true; })->listenAndWait();
![Page 70: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/70.jpg)
Email consumer
(new Consumer()) ->bind('send_email', 'emails', '*.send') ->bind('send_email', 'sms', '*.sent') ->listenTo('send_email', function($message){ $msg = json_decode($message); mail('[email protected]', 'MidwestPHP RabbitMQ Talk', $msg->message); echo 'Message sent: ' . $msg->message . PHP_EOL; return true; })->listenAndWait();
![Page 71: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/71.jpg)
![Page 72: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/72.jpg)
Now, let’s see it from the beginning
![Page 73: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/73.jpg)
![Page 75: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/75.jpg)
![Page 76: PHP, RabbitMQ, and You](https://reader034.vdocuments.mx/reader034/viewer/2022042607/554f5feeb4c905bb178b465d/html5/thumbnails/76.jpg)
Thank you. Review: joind.in/10558#midwestphp #rabbitmq
Questions? Feel free to stop and ask me, email, tweet, @[email protected]