Building real-time applications with Laravel

Laravel Montréal #11 - October 15th, 2015

Before we start ...

Thanks for comming !

Sponsors

Jobs

Get involved

Benjamin Gonzalez

  • Web Developer back-end and more recently front-end
  • Involved in PHP since 2006 with a few years off for good behaviour
  • CTO for InfoPrimes, founder of Laravel MontrĂ©al we meet every month, you are welcome :)
  • @BenjaminRosell at Github and Twitter … also on LinkedIn

Mea culpa

WARNING !

The complete exploration of all the technologies is of course beyond the scope of this presentation

WARNING !

  • jQuery
  • Pusher
  • Socket.io
  • Node.js
  • Parse notifications
  • Objective C< on demand

My first eBay purchase

Context

The limitations of HTTP

The limitations of HTTP

The HTTP protocol is half-duplex

The limitations of HTTP

What we really need us an asyncronous and continous full duplex communication protocol

WebSockets to the rescue

WebSockets to the rescue

WebSockets to the rescue

The Publisher/Subscriber pattern

Let's get our hands dirty

Please join me

RealTime with Pusher

How it works

Broadcasting events with Pusher


BROADCAST_DRIVER=pusher
PUSHER_KEY=0aba70d92427d26e79c3
PUSHER_SECRET=df1398e5ef9929ecc1f6
PUSHER_APP_ID=98291


	

composer require pusher/pusher-php-server

	

Broadcasting events with Pusher


public function bid($productId, Request $request)
{

    $lastBid = Bid::whereProductId($productId)->orderBy('amount', 'desc')->first();

    if (isset($lastBid) and $request->get('amount') <= $lastBid->amount)
        return redirect('/'.$lastBid->product->slug)->with('errors', collect(['You must bid a higher amount, idiot...']));

    $bid = Bid::create($request->all());

    Event::fire(new BidWasCreated($bid));

    return redirect('/'.Product::find($productId)->slug)->with('success', collect(['Well done my friend, keep on bidding']));
}


	

The Event Class


namespace App\Events;

class BidWasCreated extends Event implements ShouldBroadcast
{
    use SerializesModels;

    public $bid;

    public function __construct(Bid $bid)
    {
        $this->bid = $bid;
    }

    public function broadcastOn()
    {
        return ['all-users'];
    }
}


	

The Client Side


src="//js.pusher.com/3.0/pusher.min.js"

	

var pusher = new Pusher('0aba70d92427d26e79c3');

var channel = pusher.subscribe('all-users');

channel.bind('App\\Events\\BidWasCreated', function(message) {
	// your logic goes here
    $('#bids').prepend('YOUT HTML GOES HERE');

});


	

Checklist :

  • Make sure you have a Pusher account
  • Set up Queues drivers correctly
  • Boot up your workers (queue:listen)
  • Consume events from front-end
  • Parse notifications
  • Make sure the channel is OK.

Broadcasting events with Socket.io


BROADCAST_DRIVER=redis

	

"dependencies": {
	"ioredis": "^1.9.1",
	"laravel-elixir": "^3.0.0",
	"socket.io": "^1.3.7"
}

	

composer require predis/predis pda/pheanstalk && npm install

	

Broadcasting events with Socket.io


public function bid($productId, Request $request)
{

    $lastBid = Bid::whereProductId($productId)->orderBy('amount', 'desc')->first();

    if (isset($lastBid) and $request->get('amount') <= $lastBid->amount)
        return redirect('/'.$lastBid->product->slug)->with('errors', collect(['You must bid a higher amount, idiot...']));

    $bid = Bid::create($request->all());

    Event::fire(new BidWasCreated($bid));

    return redirect('/'.Product::find($productId)->slug)->with('success', collect(['Well done my friend, keep on bidding']));
}


	

The Event Class


namespace App\Events;

class BidWasCreated extends Event implements ShouldBroadcast
{
    use SerializesModels;

    public $bid;

    public function __construct(Bid $bid)
    {
        $this->bid = $bid;
    }

    public function broadcastOn()
    {
        return ['all-users'];
    }
}


	

The Node / Socket Server


var server = require('http').Server();

var io = require('socket.io')(server);

var Redis = require('ioredis');
var redis = new Redis();

redis.subscribe('all-users');

redis.on('message', function(channel, message) {
    message = JSON.parse(message);
    io.emit(channel + ':' + message.event, message.data);
});

	

node socket.js

	

The Client Side


src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.7/socket.io.min.js"

	

var socket = io('{{env('APP_URL')}}:3337/');

socket.on('all-users:App\\Events\\BidWasCreated', function(message) {
	// your logic goes here
    $('#bids').prepend('YOUT HTML GOES HERE');
});


	

Checklist :

  • ATTENTION: Production might be a challenge
  • Make sure you have a Socket.io server running
  • Make sure the socket server port is available
  • Set up Queues drivers correctly
  • Boot up your workers (queue:listen)
  • Connect correctly from front-end
  • npm install

Taking it to the next level

Further Reading

That’s All Folks!