Posted on Leave a comment

Create A Real-Time Chat App With Ionic

[callaction url=”https://www.youtube.com/user/JPlaya01″ background_color=”#333333″ text_color=”#ffffff” button_text=”Go Now” button_background_color=”#e64429″]Subscribe To My Youtube Page[/callaction]

Ionic

I figured Ionic would be a great choice for creating the mobile chat app. This chat app is dirt simple:

  1. Open up a websocket connection to the Lumen service and listen for messages
  2. Post messages to Lumen Service

Follow along, I won’t be adding any target platforms, just testing in browser. However if you want to port this that another platform just follow this guide. Let’s start! If you don’t already have the software installed type in this command npm -g install cordova ionic you may have to run this command as sudo. Afterwards cd into an empty directory and run this command

ionic start messenger-mobile blank

. It will go through the process of creating a new Ionic application, when complete cd into your new app.

Dependencies

Now we need to install our dependencies first off we need to install the socket.io-client to communicate with our real-time chat server. This is available via npm, type in this command

npm install socket.io-client

and copy the folder

node_modules/socket.io-client

to the lib folder (that’s where everything else is ionic related). Next type in this command

ionic plugin add cordova-plugin-whitelist

, this in needed because we have to access remote resources, and need to whitelist them.

Whitelisting

Open up the config.xml file at the root of your application and add this line

<meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'">

This allows us to go to any remote resource. Now we won’t get any errors trying to access our websocket. Now lets create our WebSocket factory.
 

WebSocket Factory

Create a seperate file in your www/js folder called services.js. Inside put the following code:


angular.module('services', [])
.factory('WebSocket', function($http) {
// Open a WebSocket connection
var dataStream = io('http://messenger.app:6001');
console.log(dataStream);

var messages = [];
dataStream.on('message',function(data) {
messages.push(data.message);
console.log(messages);
});
var methods = {
messages: messages,
send: function(message) {
$http.post('http://messenger.app/message',{ message:message}).success(function(data){
///messages.push(data);
//console.log(messages);
});
}
};

return methods;
});

Change http://messenger.app to the IP address of your microservice. Right now this code would break because we haven’t included the io dependecy but we will get to that.

App.js

Open www/js/app.js this is our main JS file, we are going to include our services file in here and access the WebSocket factory. Copy this code:

// Ionic Starter App
// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
angular.module('real-time-messaging', ['ionic','services'])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if(window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar) {
StatusBar.styleDefault();
}
});
})
.controller('HomeController',function($scope,WebSocket){
$scope.socket = WebSocket;
console.log($scope.socket);
$scope.messageModel = {};
$scope.sendMessage = function(){
console.log('SEND MESSAGE PUSHED!');
console.log('Message Sent ' + $scope.messageModel.message);
$scope.socket.send($scope.messageModel.message);
console.log($scope.socket.messages);
};
});

The code is pretty self explanatory, we have a single function in our HomeController that sends a message to the microservice. We have all the real time logic encapsulated in the WebSocket factory, so we are complete here!
 

Index.html

Lastly we need to modify the index.html. For simplicity sake this page only has a list to hold messages and a form to post a message. Copy the following code:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title></title>
<script src="lib/socket.io-client/socket.io.js"></script>
<link href="lib/ionic/css/ionic.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">

<!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
<link href="css/ionic.app.css" rel="stylesheet">
-->
<!-- ionic/angularjs js -->
<script src="lib/ionic/js/ionic.bundle.js"></script>

<!-- cordova script (this will be a 404 during development) -->
<script src="cordova.js"></script>

<!-- your app's js -->
<script src="js/app.js"></script>
<!-- your app's js -->
<script src="js/services.js"></script>

</head>
<body ng-app="real-time-messaging" ng-controller="HomeController">
<ion-pane>
<ion-header-bar class="bar-stable">
<h1 class="title">Real Time Messaging</h1>
</ion-header-bar>
<ion-content>
<textarea ng-model="messageModel.message" placeholder="Enter Message"></textarea>
<br>
<button ng-click="sendMessage()" class="icon icon-left ion-paper-airplane button button-positive">
Send Message
</button>

<ion-list>
<ion-item ng-repeat="message in socket.messages track by $index">
Messages:  {{message}}
</ion-item>
</ion-list>
</ion-content>
</ion-pane>
</body>
</html>

 
The app is complete! You can test it in the browser by typing ionic serve in the terminal, or you can add a platform and test on an emulator or physical device. If you have any questions, or want to see some future enhancements, please comment below!

Posted on 6 Comments

Create A Real-Time Microservice With Lumen

Laravel 6 Is Out Which Means New Lumen!

When I was at Laracon 2019 I interviewed Taylor Otwell and one of the things we talked about was new Lumen updates. I have switched to a primarily micro service mentality and I’m excited to write up scalable robust production ready microservices.

Laracon 2019 I interviewed Taylor Otwell

What Is Lumen?

Lumen is microframework provided by Laravel. I use it all the time when I need to create standalone APIs and microservices. Today I will show you how to create a generic real time microservice that can be used for later mobile back end tutorials . The microservice will take messages and push them out to all clients listening setting the ground for push notifications. Without further ado, let’s get started!

Getting Started

Because I want to focus on development, and not system administration, please follow this guide to getting your environment up and running, after doing so, go to your terminal, cd into an empty directory and type in this command or clone the repo:

lumen new real-time-microservice-skeleton

cd into your newly created app. First thing we are going to do is define our events. This microservice will give us real-time updates from those who sent messages to it. In order to provide this, we will leverage the broadcasting paradigm included in the Event class. If you are interested in a deeper understanding on how broadcasting works check here, but in short you tell the event what channel to broadcast on and you give it a driver (Redis, Pusher, log). We will being using Redis with a Node.js implementation. Before we can do any of that, we have to add a dependency or two:

For Composer:

composer require predis/predis

For NPM:

npm install --save socket.io-client

Now open up app/Providers/EventServiceProvider.php and change  the array to this:

protected $listen = [
        'App\Events\NewMessageEvent' => [
            'App\Listeners\NewMessageListener',
        ],
    ];

Event & Listener

Lumen doesn’t have generators so we have to do things manually. Now create those corresponding classes in the app/Events and app/Listeners directories respectively. In the NewMessageEvent add this code:

<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;
class NewMessageEvent extends Event implements ShouldBroadcast
{
public $message;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct($channel, $message)
{
//
$this->message = $message;
}
public function broadcastOn()
{
return new PrivateChannel('example-channel');
}
}

In the NewMessageListener it can just have the default listener code

<?php
namespace App\Listeners;
use App\Events\NewMessageEvent;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class NewMessageListener
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
    /**
     * Handle the event.
     *
     * @param  NewMessageEvent  $event
     * @return void
     */
    public function handle(NewMessageEvent $event)
    {
        //
    }
}

Routing

For the lumen skeleton I will just add two addition routes to the web.php file one GET and one POST that do the same thing. Pass a message parameter to a controller method.

<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It is a breeze. Simply tell Lumen the URIs it should respond to
| and give it the Closure to call when that URI is requested.
|
*/
$router->get('/', function () use ($router) {
    return $router->app->version();
});
$router->get('/message', 'MessageController@sendMessage');
$router->post('/message', 'MessageController@sendMessage');

Controller

The controller will have one method that calls a new event and passes the message as the parameter.

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class MessageController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
    public function sendMessage(Request $request){
      event(new \App\Events\NewMessageEvent($request->message));
    }
    //
}

Socket-IO Client

We will use Laravel Echo to interact with out redis pub/sub mechanism. Create a new file called socket-client.js and input the following

import Echo from "laravel-echo"
window.io = require('socket.io-client');
window.Echo = new Echo({
    broadcaster: 'socket.io',
    host: window.location.hostname + ':6001'
});
Echo.private('example-channel')
    .listen('NewMessageEvent', (e) => {
        console.log(e.message);
    });

As you can see we are listening for a private channel with the same name that we broadcasted on in the Event class. Now the only thing needed is an actual socket.io server. I won’t get into that in this tutorial but the official Laravel documentation recommends that you use this github package. In the next step of the tutorial I will add authentication to secure channels.

Posted on 10 Comments

Creating A Todo App With SMS Alerts In Laravel 5

[callaction url=”https://www.youtube.com/user/JPlaya01″ background_color=”#333333″ text_color=”#ffffff” button_text=”Go Now” button_background_color=”#e64429″]Subscribe To My Youtube Page[/callaction]

SMS Alerts In Laravel!

Today I am going to show you how easy it is to create a todo app with  SMS alerts in Laravel. Everything needed in including in the Laravel installation. I am using Laravel Homestead as my development machine image.
 

What Will We Be Building?

A canonical example to learn building web apps is creating a todo list app. I wanted to take the concept a step further. Wouldn’t it be nice to also receive a text message with the todo item? We will build exactly that. Building an SMS server is actually quite easy. It is as simple as sending an email to phonenumber@gateway.com a more comprehensive tutorial can be found here.  This example will also serve as an excellent use case for Laravel’s Event system. Let’s get started!
 

Steps

First thing is first, cd into an empty directory and start a new Laravel installation:

laravel new Todo

cd into your new application and lets create a new migration. We only need one model right now, a Todo model, run this command next.

php artisan make:model Todo --migration

This command not only creates our Model class for us, it also creates the db migration file too! Open your migration file @ database/migrations/MIGRATION.php and replace the old up() function with the following code.


public function up()
{
Schema::create('todos', function (Blueprint $table) {
$table->increments('id');
$table->string('content');
$table->timestamps();
});
}

Our model is extremely simple all we want to do is store a string containing our todo.
Next we are going to create a controller for our Todo model, in your terminal type in this command:
php artisan make:controller TodoController
Now open up the newly created controller file and copy this code in your store() method


//create Todo Model and
$todo = new Todo;
$todo->content = $request->content;
//$todo->save();
//launch event
event(new TodoCreatedEvent($todo));
return view('welcome');

Be sure to add

use AppTodo; and use AppEventsTodoCreatedEvent;

at the top of the page. Right now this function will break because we have not yet defined TodoCreatedEvent class, let’s create that and the TodoCreatedListener. Open up

App/Providers/EventServiceProvider.php and replace the protected $listen variable with this
protected $listen = [
'AppEventsTodoCreatedEvent' => [
'AppListenersTodoCreatedListener',
],
];

Laravel is pretty awesome about its CLI, head over to the terminal and cd into your project root and run this command

php artisan event:generate

This command will create all the events and listeners defined in the array above and scaffolds the code for you AWESOMESAUCE. Now head over to the newly created event class located at

App/Events/TodoCreatedEvent.php.

This event will do one thing, inject an Eloquent model, then pass to the listener. Laravel’s event system does an excellent job at decoupling tasks, all our our event logic will be contained in the TodoCreatedListener class. Replace the contents of your event with this:


<?php
namespace AppEvents;
use AppTodo;
use AppEventsEvent;
use IlluminateQueueSerializesModels;
use IlluminateContractsBroadcastingShouldBroadcast;

class TodoCreatedEvent extends Event
{
use SerializesModels;

public $todo;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Todo $todo)
{
//set variables
$this->todo = $todo;
}

/**
* Get the channels the event should be broadcast on.
*
* @return array
*/
public function broadcastOn()
{
return [];
}
}

See? Simple! Now let’s get into the meat over at

App/Listeners/TodoCreatedListener.php

. In this file we are only concerned with the handle() method which you can see injects an instance of our event for us! Here we are going to send an email to our cell phones (FREE TEXTS). Change your handle method to look like this:

<?php
namespace AppListeners;
use Mail;
.
.
.
.
public function handle(TodoCreatedEvent $event)
{
//set todo
$text = $event->todo->content;
Mail::raw($text, function ($message) {
$message->from(env('MAIL_USERNAME','john.smith@email.com'));
$message->to(env('PHONE','123-456-7890@gateway.com'));
});
}.

A couple things left on the backend, first off head over  to your routes file located at App/Http/routes.php add this route:


Route::post('addTodo','TodoController@store');.

Last thing to do now is edit your .env file and add all the necessary details about mail providers, as well as a phone variable to hold your number. That’s it for the backend!
All we have to do now is create a form to create the todos! Open up resources/views/welcome.blade.php and replace the contents with this:


<!DOCTYPE html>
<html>
<head>
<title>Todo SMS</title>

<link href="/css?family=Lato:100" rel="stylesheet" type="text/css">

<style>
html, body {
height: 100%;
}
body {
margin: 0;
padding: 0;
width: 100%;
display: table;
font-weight: 100;
font-family: 'Lato';
}

.container {
text-align: center;
display: table-cell;
vertical-align: middle;
}

.content {
text-align: center;
display: inline-block;
}

.title {
font-size: 96px;
}
</style>
</head>
<body>
<div class="container">
<div class="content">

<form method="POST" action="/addTodo">
{!! csrf_field() !!}

<div>
Content
<input type="text" name="content" value="{{ old('content') }}">
</div>

<div>
<button type="submit">Add Todo </button>
</div>
</form>
</div>
</div>
</body>
</html>

Test it out and try for yourself! Enjoy guys! You can see the full repo here! You can view the live app here!