- Step 0: Install Node and Redis
- Step 1: Setup and Dependecies
- Step 2: Prepare the Database
- Step 3: Create Model
- Step 4: Create Controller
- Step 5: Set up route
- Step 6: Create View
- Step 7: Create Server File
- Step 8: Test and Run
To make possible the communication from the two different backend servers, Laravel 5 and NodeJS we will use Redis. Redis is a key value storage with a publish/subscriber feature. Basically every message published on a specific queue will be intercepted from every subscriber, in this case the subscriber will be the NodeJS server.
Make sure you have node installed: Node
Mac If you have brew you can install redis easily by running this command Run
brew install redis
Then, to start the server Run
redis-server
Install Socket.io, Express, redis
Run
npm install socket.io express redis --save
Open composer.json and update the require object to include entrust:
"require": {
"php": ">=5.6.4",
"laravel/framework": "5.3.*",
"predis/predis": "^1.1"
},
Then, run
composer update
To avoid conflict with Redis in PHP environment we will modify also the alias to the Redis module of Laravel. In the config config/app.php file change
'Redis' => 'Illuminate\Support\Facades\Redis',
to
'LRedis' => 'Illuminate\Support\Facades\Redis',
For Authentication, run
php artisan make:auth
Update .env file with your database settings(db_database, db_username, db_password)
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=[db_name]
DB_USERNAME=[db_user]
DB_PASSWORD=[db_pwd]
If you install a fresh laravel project then you have already users table migration.
You need to create the messages table.
php artisan make:migration create_messages_table
messages
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateMessagesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('messages', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->text('message');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('messages');
}
}
Run
php artisan migrate
Run
php artisan make:model Message
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Message extends Model
{
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'user_id', 'message'
];
}
Run
php artisan make:controller SocketController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use LRedis, Auth;
use App\Message;
class SocketController extends Controller
{
//Write Message
public function writemessage()
{
$messages = Message::leftJoin('users', function($join) {
$join->on('messages.user_id', '=', 'users.id');
})->select(
'users.name', 'messages.message')->orderBy('messages.created_at', 'asc')
->get();
return view('writemessage', compact('messages'));
}
//Send Message
public function sendMessage(Request $request)
{
$user = Auth::user();
$input = $request->all();
$redis = LRedis::connection();
if(!isset($input['message']) || trim($input['message']) === ''){
}else{
Message::create([
'user_id' => $user->id,
'message' => $input['message']
]);
$data = ['message' => $input['message'], 'user' => $user->name];
$redis->publish('message', json_encode($data));
}
}
}
<?php
Route::group(['middleware' => ['auth']], function() {
Route::get('writemessage', ['as'=>'writemessage','uses'=>'SocketController@writemessage']);
Route::post('sendmessage', 'SocketController@sendMessage');
});
resources/views/writemessage.blade.php
@extends('layouts.app')
@section('content')
<script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script src="https://cdn.socket.io/socket.io-1.3.4.js"></script>
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2" >
<div class="panel panel-default">
<div class="panel-heading">Messages Received</div>
<div id="messages" style="height: 250px; padding: 15px;">
@foreach ($messages as $key => $message)
<p>{{$message->first_name}} : {{$message->message}}</p>
@endforeach
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div class="panel panel-default">
<div class="panel-heading">Send message</div>
<form action="sendmessage" method="POST">
{{ csrf_field() }}
<input type="text" name="message" class="message" >
<input type="submit" value="send" class="send">
</form>
</div>
</div>
</div>
</div>
<script>
var socket = io.connect('http://localhost:8890');
socket.on('message', function (data) {
data = JSON.parse(data);
$( "#messages" ).append( "<p>"+data.user+" : "+data.message+"</p>" );
});
$('input.send').click(function(e){
e.preventDefault();
search();
});
function search() {
var message = $('input.message').val();
$.ajax({
type: "POST",
url: "sendmessage",
data: { "_token": $('meta[name="csrf-token"]').attr('content'), "message": message},
cache: false,
success: function(results){
}
});
}
</script>
@endsection
In the project root folder create a new file server.js file
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var redis = require('redis');
var port_number = 8890;
server.listen(port_number, function(){
console.log("Listening on "+port_number)
});
io.on('connection', function (socket) {
console.log("new client connected");
var redisClient = redis.createClient();
redisClient.subscribe('message');
redisClient.on("message", function(channel, message) {
console.log("new message in queue "+ message + "channel");
socket.emit(channel, message);
});
socket.on('disconnect', function() {
redisClient.quit();
});
});
In the project root folder create a new file server.js file
To test the application you can start the Redis and NodeJS server.
In terminal run:
redis-server
In your project root folder run:
node server.js
In your project root folder run: node server.js
Login into you app and test by sending a message