Realtime App Using Laravel +Redis + NodeJs + AngularJS

Realtime App Using Laravel +Redis + NodeJs + AngularJS

  • 2016-08-09
  • 2603

We can combine Laravel,NodeJS,AngularJS and Redis to create an amazing product . For this tutorial i hope you know basics of angularjs , laravel and dont worry about redis , nodejs i will cover that in detail . Below are our steps for User Management Panel .

  • Laravel Installation and Configuration
  • Setting up NodeJS and Redis Server
  • Wrapping up with AngularJS
  • Final Step

How to Build a Slack Chatbot In Node.js using Botkit

View On Github

Download from Github

Laravel Installation and Configuration

Install a fresh copy of laravel and configure your database . I am using mysql as my database and redis to publish/subscribe events .
Now lets create a listener which listens to our update user event . Create a new folder inside app and name it KodeInfo , create one more folder inside app/KodeInfo and name it Handlers 
Add this to autoload classmap as below and run php artisan dump-autoload

"app/KodeInfo",
"app/KodeInfo/Handlers"
php artisan dump-autoload

Now create a new class inside our app/KodeInfo and name it UserUpdatedEventHandler

<?php
 
namespace KodeInfo\Handlers;
 
use Redis;
use Response;
 
class UserUpdatedEventHandler {
 
    CONST EVENT = 'users.update';
    CONST CHANNEL = 'users.update';
 
    public function handle($data)
    {
        $redis = Redis::connection();
        $redis->publish(self::CHANNEL, $data);
 
    }

We will create a listeners.php in app folder and will listen for event users.update . whenever users.update it will execute handle method of UserUpdatedEventHandler class which will publish our data to users.update channel . So that means we have to listen for our event users.update in  our angularjs code and act accordingly .

listeners.php

<?php
 
Event::listen(\KodeInfo\Handlers\UserUpdatedEventHandler::EVENT, '\KodeInfo\Handlers\UserUpdatedEventHandler');

Our UsersController will handle request from angularjs

UsersController.php

<?php
 
class UsersController extends BaseController {
 
    public function index(){
        return View::make('index',['rows'=>User::all(),'window'=>new \KodeInfo\JSHelper]);
    }
 
    public function addUser(){
        $user=new User();
        $user->name = Input::get('name');
        $user->email = Input::get('email');
        $user->save();
        Event::fire(\KodeInfo\Handlers\UserUpdatedEventHandler::EVENT, array(User::all()));
    }
 
    public function updateUser(){
        $user=User::find(Input::get('id'));
        $user->name = Input::get('name');
        $user->email = Input::get('email');
        $user->save();
        Event::fire(\KodeInfo\Handlers\UserUpdatedEventHandler::EVENT, array(User::all()));
    }
 
    public function deleteUser($user_id){
        User::find($user_id)->delete();
        Event::fire(\KodeInfo\Handlers\UserUpdatedEventHandler::EVENT, array(User::all()));
    }
 
    public function all(){
        return Response::json(User::all());
    }
}

We are using same view files which we have used in our previous tutorial Laravel Admin Panel . So we are using Adminlte with following directory structure

I wont be putting all views here so please have a look at views on github . We will get back to our app and work on nodejs,redis,angularjs . Below is our index.blade.php

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Laravel Realtime App</title>
    <meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
 
    {{HTML::style("/css/bootstrap.min.css")}}
    {{HTML::style("/css/font-awesome.min.css")}}
    {{HTML::style("/css/ionicons.min.css")}}
    {{HTML::style("/css/AdminLTE.css")}}
 
    <!--[if lt IE 9]>
    {{HTML::script("https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js")}}
    {{HTML::style("https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js")}}
    <![endif]-->
 
    <script>
        window.extras = window.extras || {{$window}};
    </script>
 
    @yield('styles')
    <base href="/"></base>
 
</head>
 
<body class="skin-blue" ng-app="DemoApp">
<!-- header logo: style can be found in header.less -->
 
@include('layouts.header')
 
<div class="wrapper row-offcanvas row-offcanvas-left">
    <!-- Left side column. contains the logo and sidebar -->
 
    @include('layouts.navigation')
 
    <!-- Right side column. Contains the navbar and content of the page -->
    <aside class="right-side">
 
        <div class="col-md-12">
            <div ng-view></div>
        </div>
 
 
    </aside>
    <!-- /.right-side -->
</div>
<!-- ./wrapper -->
 
<!--Template Plugins-->
{{HTML::script("/js/jquery.2.0.3.js")}}
{{HTML::script("/js/jquery-ui-1.10.3.min.js")}}
{{HTML::script("/js/bootstrap.min.js")}}
{{HTML::script("js/plugins/iCheck/icheck.min.js")}}
{{HTML::script("js/AdminLTE/app.js")}}
 
<!--AngularJS-->
{{HTML::script("https://code.angularjs.org/1.2.13/angular.js")}}
{{HTML::script("//ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular-route.js")}}
{{HTML::script("//ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular-sanitize.js")}}
{{HTML::script("//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.8/angular-ui-router.min.js")}}
 
<!--Socket.io-->
{{HTML::script("http://localhost:3000/socket.io/socket.io.js")}}
{{HTML::script("/angular/modules/angular-socket-io/socket.js")}}
{{HTML::script("/angular/app.js")}}
 
<!--Controllers and Services-->
{{HTML::script("/angular/services/users-service.js")}}
 
@yield('scripts')
 
 
</body>
</html>

In the above code we are getting some variables to angularjs so that it will be helpful . We can send csrf_token with each post request to be safe from csrf attach and so on . We are using KodeInfo/JSHelper to do so

<script>
        window.extras = window.extras || {{$window}};
</script>

We have defined a ng-view in which our list will load and have some angular scripts . Here the main part in below which we will get back soon after covering nodejs . I have seen many people get strucked in this step of how to load socket.io.js

{{HTML::script("http://localhost:3000/socket.io/socket.io.js")}}

We have also using https://github.com/btford/angular-socket-io library to easily use socket.io inside angularjs .

Setting up NodeJS and Redis Server

I was using windows at the time of writing this post so i have downloaded win64 executable from this link . It is also included with the source code .
Now download and install nodejs from nodejs website and windows users make sure you have set the path for nodejs installation folder [mine was C:\Program Files\nodejs]  . Now start command prompt/terminal and navigate to your laravel project/public directory , create a new folder nodejs and navigate to nodejs from cmd/terminal , now lets install our dependencies using below command .

npm install socket.io express redis

Now create a new file inside public/nodejs and name it server.js

var express =   require('express'),
    http =      require('http'),
    server =    http.createServer(app);
 
var app = express();
 
const redis =   require('redis');
const io =      require('socket.io');
const client =  redis.createClient();
 
server.listen(3000, 'localhost');
console.log("Listening.....");
 
io.listen(server).on('connection', function(client) {
    const redisClient = redis.createClient();
 
    redisClient.subscribe('users.update');
 
    console.log("Redis server running.....");
 
    redisClient.on("message", function(channel, message) {
        console.log(message);
        client.emit(channel, message);
    });
 
    client.on('disconnect', function() {
        redisClient.quit();
    });
});

In the above code our nodejs is listening on port 3000 . 
we have created a new redis client

const redisClient = redis.createClient();

and subscribed to users.update event

redisClient.subscribe('users.update');
 
    console.log("Redis server running.....");
 
    redisClient.on("message", function(channel, message) {
        console.log(message);
        client.emit(channel, message);
    });

Once the event is fired we will send message to all subscribers to that channel .
Now go back to our index.blade.php do you remember what i told about socket.io script . 
make sure the port which are we are using in server.js is same here .

​Wrapping up with AngularJS

Our angularjs directory structure is below

In our app.js i have defined one route so you can expand it and do not have to declare routeprovider.

app.config(['$routeProvider',
    function($routeProvider) {
        $routeProvider.
            when('/', {
                templateUrl: '/partials/users/index.html',
                controller: 'UsersController'
            }).
            otherwise({
                redirectTo: '/'
        });
    }
]);

We have defined socket factory

app.factory('socket', function ($rootScope) {
    var socket = io.connect('http://127.0.0.1:3000/');
    return {
        on: function (eventName, callback) {
            socket.on(eventName, function () {
                var args = arguments;
                $rootScope.$apply(function () {
                    callback.apply(socket, args);
                });
            });
        },
        emit: function (eventName, data, callback) {
            socket.emit(eventName, data, function () {
                var args = arguments;
                $rootScope.$apply(function () {
                    if (callback) {
                        callback.apply(socket, args);
                    }
                });
            })
        }
    };
});

Our userscontroller is basic it will load all users at startup and have methods to create , update or delete user . In our userscontroller we have listening for users.update event and get the new users set .

Final Step

Our final step is to run our redis server with admin rights , run our server.js using node which can be done like below in terminal / cmd

node server.js

I have also created a migration make sure to run

php artisan migrate

You can also monitor redis request using redis-cli monitor
Now navigate to / route and you will see all users

Output:

enter image description here

Watch video

Suggest

Learn and Understand NodeJS

Learn Nodejs by Building 12 Projects

Quickstart AngularJS

JavaScript Promises: Applications in ES6 and AngularJS

Learn Angular 2 Development By Building 10 Apps