Using Laravel Echo in conjunction with Socket.io and Vue SPA.

Pusher is the easiest to configure, but since it requires an additional subscription, We've opted for Socket.io and Redis instead.

php
php coding
javascript
socket.io with php

Let's begin by setting up our backend. Configuration is accomplished through the.env file at the application's root.

BROADCAST_DRIVER=redis
    CACHE_DRIVER=file
    QUEUE_CONNECTION=sync
    SESSION_DRIVER=file
    SESSION_LIFETIME=120
    REDIS_PASSWORD=null
    REDIS_PORT=6379

We must replace BROADCAST DRIVER with Redis and alter the ports on which Redis can operate. The config/database.php file contains a Redis-specific setting.

'redis' => [

      'client' => env('REDIS_CLIENT', 'phpredis'),

      'options' => [
          'cluster' => env('REDIS_CLUSTER', 'redis'),
          'prefix' => '',
      ],

      'default' => [
          'url' => env('REDIS_URL'),
          'host' => env('REDIS_HOST', '127.0.0.1'),
          'password' => env('REDIS_PASSWORD', null),
          'port' => env('REDIS_PORT', '6379'),
          'database' => env('REDIS_DB', '0'),
      ],

      'cache' => [
          'url' => env('REDIS_URL'),
          'host' => env('REDIS_HOST', '127.0.0.1'),
          'password' => env('REDIS_PASSWORD', null),
          'port' => env('REDIS_PORT', '6379'),
          'database' => env('REDIS_CACHE_DB', '1'),
      ],

  ],
];

As you can see, We are using phpredis as the Redis client by default. This requires us to install Redis on the Homestead server.

## Let's ssh into the box
$ homestead ssh

## Install Redis
$ pecl install redis

## Install phpredis
$ sudo git clone https://github.com/phpredis/phpredis.git
$ sudo mv phpredis/ /etc/

echo server configuration for laravel

Now, we require a method for running our server for socket.io communication. The laravel-echo-server package will be implemented.

## On our homestead box
$ npm install -g laravel-echo-server

## In your project root
$ laravel-echo-server init

The init method initiates the setup procedure for your echo server.

? Do you want to run this server in development mode? Yes

? Which port would you like to serve from?6001

? Which database would you like to use to store presence channel members? 
redis

? Enter the host of your Laravel authentication server. 
your-domain.test

? Will you be serving on http or https? http

? Do you want to generate a client ID/Key for HTTP API? 
No

? Do you want to setup cross domain access to the API?
Yes

? Specify the URI that may access the API: *

? Enter the HTTP methods that are allowed for CORS: 
GET, POST

? Enter the HTTP headers that are allowed for CORS:
Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id

? What do you want this config to be saved as? 
laravel-echo-server.json

This procedure will generate your server's configuration. For Laravel authorization, I'm also use API namespace, therefore I modified the generated.json file.

{
  ...
  "authEndpoint": "/api/broadcasting/auth",
  ...
}

Now authentication will function through a call to the 'API' namespace route that supports all of my Laravel authorization guards.

We've added laravel-echo-server.json to.gitignore to set it up independently on staging and production servers, but you can alternatively use an.env file to replace the settings.

If a.env file is present in the same directory as laravel-echo-server.json, the following options can be overwritten:

# Note: This option will fall back to the LARAVEL_ECHO_SERVER_HOST option as the default if that is set in the .env file.
authHost: LARAVEL_ECHO_SERVER_AUTH_HOST
host: LARAVEL_ECHO_SERVER_HOST
port: LARAVEL_ECHO_SERVER_PORT
devMode: LARAVEL_ECHO_SERVER_DEBUG
databaseConfig.redis.host: LARAVEL_ECHO_SERVER_REDIS_HOST
databaseConfig.redis.port: LARAVEL_ECHO_SERVER_REDIS_PORT
databaseConfig.redis.password: LARAVEL_ECHO_SERVER_REDIS_PASSWORD
protocol: LARAVEL_ECHO_SERVER_PROTO
sslKeyPath: LARAVEL_ECHO_SERVER_SSL_KEY
sslCertPath: LARAVEL_ECHO_SERVER_SSL_CERT
sslPassphrase: LARAVEL_ECHO_SERVER_SSL_PASS
sslCertChainPath: LARAVEL_ECHO_SERVER_SSL_CHAIN

enabling echo server for laravel

The last step is to keep the Laravel Echo Server active. This step will differ between forge managed servers and homestead installations.

homestead hosting laravel echo server

After configuring your server, you must execute a few instructions to ensure that the server is working.

# On homestead machine
$ cd /etc/supervisor/conf.d
$ touch laravel-echo.conf

# Edit this new file using nano or vim and add this
[program:laravel-echo]
directory=/home/vagrant/[path_to_your_project]
process_name=%(program_name)s_%(process_num)02d
command=laravel-echo-server start
autostart=true
autorestart=true
user=vagrant
numprocs=1
redirect_stderr=true
stdout_logfile=/home/vagrant/[path_to_your_project]/storage/logs/echo.log
stderr_logfile=/var/log/supervisor/test.err.log

# Lets reload the configuration and start the daemon
$ sudo supervisorctl reread
$ sudo supervisorctl restart all 
laravel-echo:laravel-echo_00: started

The Laravel Echo Server will then be kept alive and made available to the front end application.

using forge to operate laravel echo server

On Forge, it is significantly simpler to run Laravel Echo Server than on Homestead. Our server requires only the configuration of a daemon.

To add a new one, complete out the fields.

# Command
/usr/bin/laravel-echo-server start

# User
Forge

# Directory
/home/forge/[project-domain]

This is it! You may check the status of your process in Laravel Forge after beginning it.

configuring laravel echo for vue spa

To integrate Laravel Echo with our front-end application, we will need to install a Laravel Echo package for the front end and a Socket.io package.

# In your front-end app root directory
$ yarn add laravel-echo socket.io

We've configured Laravel Echo in a file named echo.js, so that it can be imported into components as needed. The configuration file is displayed below.

import Vue from 'vue'
import Echo from 'laravel-echo'
import Cookies from 'js-cookie'

window.io = require('socket.io-client')

export var echo_instance = new Echo({
  broadcaster: "socket.io",
  host: process.env.VUE_APP_BACKEND_APP + ':6001',
  auth: {
    headers: {
        /** I'm using access tokens to access  **/
      Authorization: "Bearer " + Cookies.get('access_token')
    }
  }
})

Vue.prototype.$echo = echo_instance

export default Vue

We use socket.io as a broadcaster. With the exception of the authorisation header, the remainder of the setting is really straightforward. Bearer token is used to authenticate users and provide access to Laravel channels.

tune in to broadcasts

With Laravel Echo, there are multiple ways to listen for changes. Several of them have been implemented in the application on which I am presently working.

In the application's root component, I am initiating a connection to each user's notifications channel.

this.$echo.private(user.$ {this.user.id})
.notification((notification) => {
    this.handleNotification(notification)
})

After the user logs in, the component calls the method containing the snippet.

The other scenario involves adjustments in real time on private channels. This was utilized in the application to monitor changes to running timers.

this.$echo.private(timers.$ {this.game.timer.id})
.listen('.timer.updated', (e) => {
  this.timer = e.timer
  this.initializeTimer()
});

When the component is mounted, this function is invoked to connect the user to the relevant channel and to always listen for changes made by other users in order to display consistent data.

([ioredis] unhandled error event: connect) econnrefused 192.168.10.10:6379)

Our Echo server was unable to connect to Redis after I migrated my project to a more modern machine. This was the result of a configuration gap in Redis configuration.

When attempting to run the Laravel echo server, the following problem appeared:

$ [ioredis] Unhandled error event: Error: connect ECONNREFUSED 192.168.10.10:6379

ssh into the homestead machine:

$ sudo nano /etc/redis/redis.conf // edit this file

Add an IP bind command to the Network section of the configuration file /etc/redis/redis.conf:

 ################################## NETWORK #####################################

# By default, if no "bind" configuration directive is specified, Redis listens
...
#
# Examples:
#
# bind 192.168.1.100 10.0.0.1
# bind 127.0.0.1 ::1
#
# ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the
...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bind 127.0.0.1 ::1
bind 127.0.0.1 192.168.10.10 // Add this