Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

mstnorris's avatar

Step by Step Guide to Installing Socket.io and Broadcasting Events with Laravel 5.1

I've decided to put together a guide to help others in setting up socket.io within their projects. I hope you find this resource useful.

A big big shout out goes to @toniperic for helping me get socket.io up and running. You can view the original article where I got some of the information from; this guide builds upon it drastically, fills in the gaps, and is brought it up to date.

Please excuse any mistakes in this walkthrough, the Markdown wasn't being parsed correctly while I wrote it. I will edit it in situ within the Laracasts Forum when I spot errors. If you feel I should elaborate anywhere or amend anything please let me know below.

~~At the time of writing this (3 Jun 2015) Laravel 5.1 hasn't been released. It is due for release on 9 Jun 2015 so it certainly isn't long to go. I thought I'd get a head start on the game and put together this guide from different sources I found online.~~

In this walkthrough I'll assume you're using Laravel Homestead.

Prerequisites

Laravel Homestead already includes Node and Redis but just to check that they are installed and working correctly.

  1. SSH into your Homestead VM

  2. run node -v

    You will see something like "v0.10.33"

  3. run redis-cli ping

    You should see "PONG"

Create a New Project

  1. You will need to get the latest version of Laravel and depending on when you read this you will have to do one of the follow.

Using composer like so:

  • composer create-project laravel/laravel your-project-name dev-develop (to get the very latest release [may be unstable])
  • composer create-project laravel/laravel your-project-name

Or using the laravel new command:

  • laravel new your-project-name
  1. Edit your /etc/hosts file on your host OS.

    Add the line

  • "192.168.10.10 your-project-name.app"
  1. While SSH'd into Homestead run
  • serve your-project-name.app /home/vagrant/Code/path/to/public/directory 80
  1. Staying SSH'd into Homestead
  • cd your-project-name

Install packages

  1. npm install express ioredis socket.io --save

    Your package.json file will look like

{
  "private": true,
  "devDependencies": {
    "gulp": "^3.8.8",
    "laravel-elixir": "*"
  },
  "dependencies": {
    "express": "^4.12.4",
    "ioredis": "^1.4.0",
    "redis": "^0.12.1",
    "socket.io": "^1.3.5"
  }
}
  1. composer require predis/predis

    The require part of your composer.json file will look like

"require": {
    "laravel/framework": "5.1.*",
    "predis/predis": "^1.1@dev"
},

Creating the Event

  1. php artisan make:event EventName

    Open up your newly create EventName.php event class found within the app/Events directory.

  2. Make sure that it implements ShouldBroadcast

class EventName extends Event implements ShouldBroadcast
  1. The entire EventName.php class should look like
<?php namespace App\Events;

use App\Events\Event;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;

class EventName extends Event implements ShouldBroadcast
{
    use SerializesModels;

    public $data;

    public function __construct()
    {
        $this->data = array(
            'power'=> '10'
        );
    }

    public function broadcastOn()
    {
        return ['test-channel'];
    }
}

Setting up the Views

  1. Create a new view master.blade.php within the resources/views/layouts directory.
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>FiveOne Socket.io</title>
</head>
<body>
@yield('content')

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
@yield('footer')
</body>
</html>
  1. Create a second view that extends the master view above. I've called it test.blade.php. Put this in the resources/views directory.
@extends('layouts.master')

@section('content')
    <p id="power">0</p>
@stop

@section('footer')
    <script src="{ { asset('js/socket.io.js') } }"></script>
    <script>
        //var socket = io('http://localhost:3000');
        var socket = io('http://192.168.10.10:3000');
        socket.on("test-channel:App\\Events\\EventName", function(message){
            // increase the power everytime we load test route
            $('#power').text(parseInt($('#power').text()) + parseInt(message.data.power));
        });
    </script>
@stop

Routing

  1. Set up three routes like so. Add them to your app/Http/routes.php file.
Route::get('/', function() {
    // this doesn't do anything other than to
    // tell you to go to /fire
    return "go to /fire";
});

Route::get('fire', function () {
    // this fires the event
    event(new App\Events\EventName());
    return "event fired";
});

Route::get('test', function () {
    // this checks for the event
    return view('test');
});

Create the socket.js file

  1. Create a new file in your project root socket.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var Redis = require('ioredis');
var redis = new Redis();
redis.subscribe('test-channel', function(err, count) {
});
redis.on('message', function(channel, message) {
    console.log('Message Recieved: ' + message);
    message = JSON.parse(message);
    io.emit(channel + ':' + message.event, message.data);
});
http.listen(3000, function(){
    console.log('Listening on Port 3000');
});

Setting up Redis

As mentioned above Redis should already be installed but you just need to edit your .env file to tell Laravel to use the correct BROADCAST_DRIVER. Add the following line.

BROADCAST_DRIVER=redis

Starting the Servers

  1. Open two command line tabs and SSH into Homestead

    • cd into the root directory of your project

    • In the first tab, run node socket.js

      You should see "Listening on Port 3000"

    • In the second tab run redis-server --port 3001

      You should see a lot of output

Trying it out

  1. Open up two browser windows side by side and in the first one hit the URL:
  1. And in the second:
  1. Keep refreshing the first window and you should see the second page's content increment.

  1. You're all done!

  2. (I had to make this point (a) to make it an even 20! and (b) to kindly ask for your feedback. If follow this guide and you get stuck anywhere, or it doesn't make sense, or anything really, please let me know.)

0 likes
133 replies
Shaun's avatar

Great guide!! Thank you for taking the time to put it all together. Can't wait to give this a try.

4 likes
JohnRivs's avatar

I'd upvote your post a million times.

11 likes
mstnorris's avatar

Thanks for the kind words guys, I hope you find it useful. I haven't built it out yet as I wanted to put the guide together with the smallest amount of code needed and I think this is it.

As I mentioned, if you stumble anywhere, or something isn't clear please do let me know.

5 likes
olimorris's avatar

This is such a good post. @mstnorris I really respect your posts. They add value and content and I don't think I've ever seen you ask for anyone's help, you only ever contribute. Many thanks!

I'd be interested to know how people use this with Laravel Forge. I.e. Install socket.io and get it up and running. Particularly with a horizontally scalled node which houses the socket.io server that is linked to the main server.

1 like
mstnorris's avatar

@olimorris thank you so much for those very kind words. I think I ask more questions than you realise but I hope I do it in a way that it helps others too which is why I created the Guidelines for posting on Laracasts.com. It is how I like to see questions being asked as it is easier to understand so of course that is how I approach it when I ask questions of my own.

Well as I am running a Digital Ocean server provisioned with Forge I shall let you know. I plan on tackling that either tomorrow or early part of next week and I will document my process then too.

Thank you again.

3 likes
Kryptonit3's avatar

@mstnorris

few things...

One thing I noticed is you didn't put to include socket.io in the footer

<script src="https://cdn.socket.io/socket.io-1.3.5.js"></script>

Also, how would I go about setting up redis and socketio to run in the background and to restart if the server should restart. I do not want to have to keep a terminal window open 24/7.

Thanks!

3 likes
mstnorris's avatar

@Kryptonit3 check out Supervise This. You'd do exactly that using a service called Supervisor.

Also, I will add the missing script tag later as I'm going to run through the above to make sure I can do it all from scratch on a clean install.

1 like
Kryptonit3's avatar

@mstnorris I will watch the video. If it isn't too much to ask, could you outline getting those services to run automatically with supervisor when you run through it again?

mstnorris's avatar

@lstables I chose to go with socket.io as Pusher starts charging when you go over 20 connections. A connection is any open channel to Pusher; meaning that as soon as more than 20 people (each have a browser open to your app) are on the site simultaneously then you will have to start paying. Or if 10 people each have two browser windows open, then you'll go above 20 connections!!!.

Also, there may be latency issues with the HTTP requests while accessing Pusher whereas it is instant with socket.io. It is minimal JavaScript and in all honesty very easy to set up (following the guide above). I'm not too familiar with JavaScript and I got through it with some help and other resources.

2 likes
theUnforgiven's avatar

@mstnorris yes going to follow your guide through, just thought I'd share a resource should anyone want to use Pusher too, how about setting this up on Forge is that the same as on Homestead ? Just SSH in and install required libs?

mstnorris's avatar

@lstables I haven't uploaded it to my DO box yet (I'm using Forge too). I will document the process and add to this guide.

theUnforgiven's avatar

Ok that would cool, see how you get on first then before I do it lol

1 like
theUnforgiven's avatar

Sorry @mstnorris I really meant to say, I'm just finishing something off first before I need to events first, but if I do get around to before you I will help out.

VladimirRakita's avatar

@mstnorris I don't know what is wrong with my code, I did everything you described and keep getting this in chromes console

GET http://192.168.10.10:3000/socket.io/?EIO=3&transport=polling&t=1434051560676-18 net::ERR_CONNECTION_REFUSED17.Request.create @ socket.io.js:2919Request @ socket.io.js:284217.XHR.request @ socket.io.js:277317.XHR.doPoll @ socket.io.js:280318.Polling.poll @ socket.io.js:319218.Polling.doOpen @ socket.io.js:313614.Transport.open @ socket.io.js:231313.Socket.open @ socket.io.js:1743Socket @ socket.io.js:1625Socket @ socket.io.js:15603.Manager.open.Manager.connect @ socket.io.js:299(anonymous function) @ socket.io.js:564 socket.io.js:2919 GET http://192.168.10.10:3000/socket.io/?EIO=3&transport=polling&t=1434051567678-19 net::ERR_CONNECTION_REFUSED

Anybody knows what could be wrong?

Thanks.

mstnorris's avatar

Have you run redis-server and node socket.js ?

1 like
Jonathan's avatar

Thanks for the guide. I'm also curious on how you would set this up on a production environment.

1 like
mstnorris's avatar

@Jonathan I will document my progress and upload it here, it will take me a few days to complete but favourite this thread to be notified of any updates :D

1 like
VladimirRakita's avatar

@mstnorris No, I didn't. Now everything work as it should :)

Thank you for this amazing guide!

Edit: Problem was that I have typed node socket.js in root of my project instead to ssh to vm and then start node.

2 likes
theUnforgiven's avatar

@mstnorris LEGEND! I've set this up in like 10 mins all running as planned, now to figure out how to get it working on Forge.

1 like
theUnforgiven's avatar

I'm wanting to add something like Jeff has on this forum that says something as been updated by a name coming from the database when this happens.

Using your method @mstnorris how would acheive this?

REBELinBLUE's avatar

Something which other people may want to know, if your client is behind a firewall which doesn't allow outbound connections to random ports such as port 3000 your websocket may not work (for instance some companies only allow connections to port 80 and 443).

If you are using nginx you can set up a reverse proxy

upstream websocket {
    server 127.0.0.1:3000;
}

then in the server section add

location /socket.io {
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_pass http://websocket;
}

then all you need to do is change the client code to

var socket = io('http://192.168.10.10');

socket.io will automatically connect to /socket.io and nginx will proxy it to node for you

you can apparently change the path socket.io uses by adding a json object as the second parameter to io() with a resource key like

var socket = io('http://192.168.10.10', { resource: '/mysocket' } );

but I have not tried it to confirm (you would need to change the location in nginx to /mysocket/socket.io also)

Also, the socket.io server will serve the required JS so you don't have to use the socket.io CDN you can just do

<script src="http://192.168.10.10:3000/socket.io/socket.io.js"></script>
6 likes
theUnforgiven's avatar

How would one setup notifications like Jeff has on the forum when someone leaves a reply a flash message is applied, I'm new to events and don't quite understand the concept of passing data and stuff through, so some examples on this type of stuff would be ideal.

Next

Please or to participate in this conversation.