Oke, tadi sudah ngetik panjang lebar dan terlalu detail “how to”-nya. Tapi setelah dibaca-baca lagi, malah ribet, dan esensinya gak dapet. Jadi saya rewrite supaya lebih pendek supaya lebih mudah dipahami 😐

Overview

Alkisah Taylor Otwell nambahin fitur Broadcast baru di Laravel 5.1 agar realtime push notification lebih mudah dibuat. Saat ini hanya ada dua driver. Yaitu untuk Pusher dan untuk Redis. Jika anda menggunakan layanan lain, anda tingal menulis code sendiri dengan mengimplement Illuminate/Contracts/Broadcasting/Broadcaster.

Dan bagi anda yang tidak menggunakan Laravel, gampang aja. Fitur ini tidak bergantung pada Laravel kok alias framework agnostic. Misalnya anda menggunakan Panada Framework, Yii, Lumen, Silex, Phalcon atau tanpa framework tinggal gunakan saja https://github.com/illuminate/broadcasting. Enak kan? πŸ˜€

Let’s get started

Hal-hal yang kita butuhkan untuk praktek adalah:

  • Redis,
  • Web socket server,
  • Web socket client,
  • Laravel 5.1

Untuk web socket server anda bisa menggunakan apapun. Anda bisa menggunakan Go, NodeJS/IO.js, Scala, dll. Mungkin juga bisa menggunakan winsock.dll yang ada di Windows atau System.Net.Sockets.Socket yang ada di .Net Framework :/ Hmm… ntar deh coba jajal kalo ada komputer yang pake Windows nganggur.

Anyway yang penting spesifikasinya mengikuti RFC 6455. Tapi disini saya memberi contoh menggunakan NodeJS/IO.js + Socket.io. Mungkin berikutnya saya coba pakai RatchetPHP. Karena di production saya pakai RatchetPHP :/.

Lanjutt… Begitupula dengan web socket client, anda bisa menggunakan apapun. Tidak hanya JS, misalnya menggunakan PHP, Go, dll. Yaaa siapa tau anda bikin aplikasi yang nggak jalan di web browser. Tapi disini saya menggunakan Socket.io client sebagai contoh.

Anda bisa cari tau sendiri bagaimana cara install Redis di system anda. Jika anda menggunakan Homestead, kita bisa langsung mulai. Karena di Homestead, semua sudah pre-installed.

Disini kita coba bikin fitur notifikasi sederhana. Kalau ada user yang melakukan registrasi, maka otomatis akan mengirimkan notifikasi ke administrator dashboard.

Saya asumsikan sudah cukup familiar dengan Laravel, sehingga beberapa tahap tidak akan saya jelaskan.

Start!!

Edit file config/broadcasting.php, ganti driver dari pusher menjadi redis.

Generate event dan listener. Kira-kira seperti ini di App/Providers/EventServiceProvider.php

protected $listen = [
    'App\Events\UserRegistrationEvent' => [
        'App\Listeners\UserRegistration\SendSmsNotification',
        'App\Listeners\UserRegistration\SendEmailNotification',
        'App\Listeners\UserRegistration\SendWebNotification',
    ],
];

Lalu gunakan php artisan event:generate untuk generate event dan listener class.

Cara lain anda bisa menggunakan

php artisan make:event UserRegistrationEvent
php artisan make:listener UserRegistration/SendSmsNotification
php artisan make:listener UserRegistration/SendMailNotification
php artisan make:listener UserRegistration/SendWebNotification

Lalu edit file App/Providers/EventServiceProvider.php seperti diatas.

Btw, kita gak bahas Sms dan Mail notification. Ini cuma supaya dapat gambaran kalau kita trigger satu event, maka hal-hal dibelakang event tersebut bisa jalan. Juga ini dapat membuat controller anda tetap clean, karena masing-masing notifikasi bertanggung jawab didalam class-nya sendiri-sendiri.

Edit file App/Events/UserRegistrationEvent.php, ubah kira-kira menjadi seperti ini

<?php namespace App\Events;

use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class UserRegistrationEvent implements ShouldBroadcast
{
    public $name;

    public $email;

    public function __construct(array $payload)
    {
        $this->name  = $payload['name'];
        $this->email = $payload['email'];
    }

    public function broadcastOn()
    {
        return ['user_registration'];
    }
}

Buat suatu yang akan menggunakan event ini. Sebagai contoh, kita tambahin saja di file App/Http/Controllers/Auth/AuthController.php pada create method

protected function create(array $data)
{
    $user = User::create([
        'name' => $data['name'],
        'email' => $data['email'],
        'password' => bcrypt($data['password']),
    ]);

    event(new UserRegistrationEvent($data)); // trigger the event

    return $user;
}

Web Socket Server

Kita install dulu package yang dibutuhkan untuk membuat socket server dengan nodejs + socket.io

npm install --save socket.io redis express

Lalu buat file socket.js yang isinya

var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var redis = require('redis');

server.listen(9090);

io.on('connection', function (socket) {

    var redisClient = redis.createClient();

    redisClient.subscribe('user_registration');

    redisClient.on('message', function(channel, message) {
        socket.emit(channel, message);
    });

    socket.on('disconnect', function() {
        redisClient.quit();
    });

});

Jalankan dengan

node socket.js

Web Socket Client

Tambahkan ini di view anda yang akan menampilkan log dari aktifitas registrasi

<div id="notifications"></div>

<script src="//cdn.socket.io/socket.io-1.3.5.js"></script>
<script>
  var socket = io('http://localhost:9090');
  
  socket.on('message', function (msg) {
    console.log(msg);

    var notif = document.getElementById('notifications');

    var div = document.createElement('div');

    div.innerHTML = msg.name + '('+ msg.email +') baru saja mendaftar';

    notif.appendChild(div);
  });
</script>

Selesai

Redis PubSub

Tadaa… selesai πŸ™‚ Sekarang tiap kali user melakukan registrasi, suatu event akan di-trigger dan akan memberikan notifikasi ke admin.

Gambar diatas, pada kiri atas adalah redis server. Kebetulan nggak dijadiin daemon. Lalu di kiri bawah untuk ngeliat proses yang terjadi dengan redis-cli. Kanan atas artisan serve, dan kanan bawah web socket server.

Btw, source code-nya menyusul yaa πŸ˜€

Disini bisa dicoba source code-nya https://github.com/mul14/laravel-5.1-broadcast-example

Kalau ada pertanyaan dan counter attack silahkan tulis di kolom komentar.

Iklan

44 pemikiran pada “Laravel 5.1: Easy Realtime Push Notification

    1. Supaya cuma ngurus cuma satu repository. Gak perlu bikin dua repo, satunya node, satunya php. Ngurus lagi package-nya kalo ada update. Deploy kalo dua kan juga lebih repot, walaupun bisa di-automate-tapi tetep harus dipantau. Kalau ada orang baru yang join ke team juga belum tentu dia bisa node.

  1. mas itu yang di App/Listeners/UserRegistration/SendWebNotification.php itu kok seperti file App/Events/UserRegistrationEvent.php , atau itu file emang sama atau salah ketik? Di Source code yg diubah yg event mail ya, gk jadi web notif?

    1. Hai, thanks. Ini kesalahan ketik. Sudah saya perbaiki.

      Yang di source code. Hmm… saya lupa 😐
      Gimana kalau dicoba aja? Seingat saya sih sudah jalan normal.

  2. Hi Mas Mul…
    Makasih buat tutorialnya, work perfect di local server…
    tapi pas saya coba di production mode (live server centos 7)
    koq ga jalan ya, di running node server.js koq ga ada lognya sama sekali, padahal udah saya install semua, redis-server , nodejs, npm..

    kalo mau tau ini kesalahannya di antara (redis-server , nodejs, npm) gimana ya check nya??

    Makasih πŸ™‚

  3. Wah keren ..
    masih newbie, selama ini ngebayanginnya untuk realtime notifikasi itu : pake fungsi sleep/interval di js clientnya untuk ngambil info terbaru setiap beberapa waktu hehe

  4. Om, kalau kasusnya ngasi notifikasi yg udh di jadwal di db gmna? Misal jam 12 waktunya makan… pas kebetulan buka webnya ntr kluar notif… πŸ˜€

  5. errornya kenapa ya?
    pas buka http://localhost:8000/admin
    baru error..

    7 Jun 18:35:17 – Listening at http://0.0.0.0:9090
    7 Jun 18:35:21 – New client connected
    events.js:141
    throw er; // Unhandled ‘error’ event
    ^

    Error: Redis connection to 127.0.0.1:6379 failed – connect ECONNREFUSED 127.0.0.1:6379
    at RedisClient.on_error (E:\project\laravel-5.1-broadcast-example\node_modules\redis\index.js:196:24)
    at Socket. (E:\project\laravel-5.1-broadcast-example\node_modules\redis\index.js:106:14)
    at emitOne (events.js:77:13)
    at Socket.emit (events.js:169:7)
    at emitErrorNT (net.js:1253:8)
    at nextTickCallbackWith2Args (node.js:442:9)
    at process._tickCallback (node.js:356:17)

  6. saya coba source code dari yg om mul sediain..
    pas buka localhost/admin errornya kyk dibawah:
    kenapa ya?
    NB: windows / php artisan serve

    7 Jun 18:56:23 - Listening at http://0.0.0.0:9090
    7 Jun 18:56:27 - New client connected
    events.js:141
          throw er; // Unhandled 'error' event
          ^
    
    Error: Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED 127.0.0.1:6379
        at RedisClient.on_error (E:\project\laravel-5.1-broadcast-example\node_modules\redis\index.js:196:24)
        at Socket. (E:\project\laravel-5.1-broadcast-example\node_modules\redis\index.js:106:14)
        at emitOne (events.js:77:13)
        at Socket.emit (events.js:169:7)
        at emitErrorNT (net.js:1253:8)
        at nextTickCallbackWith2Args (node.js:442:9)
        at process._tickCallback (node.js:356:17)
      1. maksudnya sudah diinstall atau blm gmn ya ?
        soalnya ada error seperti ini, dan server redisnya sudah jalan

        c:\xampp\htdocs\realtime\temp>node socket.js
        events.js:160
        throw er; // Unhandled ‘error’ event
        ^

        Error: listen EADDRINUSE :::9090
        at Object.exports._errnoException (util.js:1026:11)
        at exports._exceptionWithHostPort (util.js:1049:20)
        at Server._listen2 (net.js:1257:14)
        at listen (net.js:1293:10)
        at Server.listen (net.js:1389:5)
        at Object. (c:\xampp\htdocs\realtime\temp\socket.js:6:8)
        at Module._compile (module.js:570:32)
        at Object.Module._extensions..js (module.js:579:10)
        at Module.load (module.js:487:32)
        at tryModuleLoad (module.js:446:12)

      2. Dibaca mas error message-nya

        Error: listen EADDRINUSE :::9090

        Error Address In Use -> Address 127.0.0.1 dengan port 9090 sudah digunakan. Jadi solusinya gunakan port lain.

      3. ngga bisa juga mas

        server redis sudah jalan
        kemudian saya juga udah buka redisnya utk liat log nya
        dan ketika saya coba create data baru tetap ga jalan
        masalahnya dmn ya mas ?
        oh iya, urlnya saya jalankan seperti ini localhost:8080/belajar/index.php
        apa salah ?
        saya juga sudah tes buka link localhost:9090/ ditulis can’t get / seperti itu.

  7. saya coba source code yang di gituhub,
    beres diinstal dijalankan node server.js
    tapi hanya berhenti sampe di
    Listening at http://0.0.0.0:9090

    tidak ada tulisan new client connected

    ketika submit . di admin tidak terjadi apa2.

    saya buka redis-cli> SUBSCRIBE notification muncul sepeerti ini

    127.0.0.1:6379> SUBSCRIBE notification
    Reading messages… (press Ctrl-C to quit)
    1) “subscribe”
    2) “notification”
    3) (integer) 1
    1) “message”
    2) “notification”
    3) “{\”event\”:\”App\\\\Events\\\\UserRegisteredEvent\”,\”data\”:{\”user\”:{\”name\”:\”demo\”,\”email\”:\”demo@example.com\”}}}”

    apa yang salah?

    saya menggunakan homestead di windows10

      1. kalo utk ngetes
        jalanin redis,node app.js, ama queue:listen harusnya ga ada masalah ya?

        kalo untuk production
        node app.js untuk semua website? atau app.jsnya per masing-masing project ya?

    1. edit: skrg masalahnya si laravel selalu request redis dari localhost om, padahal redis saya diinstall di server yang berbeda. Makanya selalu error “No connection could be made because the target machine actively refused it. [tcp://127.0.0.1:6379]”

      Solusinya gmn ya?

      Makasih sebelumnya

Tinggalkan Balasan

Please log in using one of these methods to post your comment:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s