Do you have used Elvis Operator in PHP?

I am not a good PHP programmer, I use the language to work on projects that are not product base. And usually I work on the project myself. Because I do it by myself, I code it according to what I learned myself.

I am not know what the version of PHP before, is your code working in PHP version 5.6 or 7+ version?

I am not aware thats. But now, i need to know that deeply because we create product base mean customer will not break our product. I now always care about other programmer write their code.

Continue reading Do you have used Elvis Operator in PHP?

Notes Laravel Scheduler Function onOneServer()

I once worked with devops that did a lot of settings on the server. And he doesn’t have basic PHP. Then he asks about the function scheduler to run on only one server / one instance.

Continue reading Notes Laravel Scheduler Function onOneServer()

Tahun Pertama Pengalaman Bekerja Remote Di Rumah

Saya sempat menulis artikel kenapa saya seneng bekerja remote dan saya bersyukur Allah mengizinkan saya bekerja remote di rumah selama 1 tahun ini. Saya ingin berbagi pengalaman bekerja mencari nafkan di rumah tanpa ngantor. Berikut beberapa point saya akan coba berbagi pengalaman bekerja secara remote ini.

Continue reading Tahun Pertama Pengalaman Bekerja Remote Di Rumah

Memulai hari keluarga tanpa Televisi dan mengurangi Handphone untuk anak

Saya sudah ada beberapa tahun lalu ingin menjual TV. Alasan klasik, TV tidak bagus buat anak-anak sepengetahuan saya. Kita sudah arahkan ke channel seperti Ipin Upin atau Kartun lainnya yang lebih baik namun tetep saja saya lihat dari segi iklan dan tayangan lain yang secara tidak langsung anak akan melihat seperti iklan film horor indonesia yang kadang nge-blast masuk saat anak menonton acara kartun si anak.

Continue reading Memulai hari keluarga tanpa Televisi dan mengurangi Handphone untuk anak

Kenapa saya seneng bekerja remote

Tulisan ini saya tulis berdasarkan pengalaman saya sendiri saat mulai bekerja di tahun 2011 sampai kini 2019. Harapan tentu mungkin bisa jadi bacaan buat orang seprofesi (IT Programmer) yang mungkin ada kesamaan dengan kondisi saya selama bekerja. Jika dirasa kurang cocok wajar saja karena setiap individu memiliki sejarah hidup masing-masing dengan pemikiran dan pendidikan yang mereka alami juga masing-masing.

Continue reading Kenapa saya seneng bekerja remote

Belajar Laravel: Validasi nomor telpon dengan package Propaganistas

Validasi nomor telpon sebenarnya susah susah mudah. Sebelum membahas susah susah mudahnya itu ada baiknya kenapa kita perlu melakukan validasi terhadap nomor telpon yang kadang perlu dilakukan di aplikasi yang kita buat.

Continue reading Belajar Laravel: Validasi nomor telpon dengan package Propaganistas

Blade Error Directive Pada Laravel 5.8.13

Sore ini dapat email dari Laravel News, terdapat beberapa perubahan pada Laravel 5.8.13 yang salah satunya adalah Directive Blade terbaru untuk menangani error. Walaupun mungkin Blade ini sudah mulai ditinggalkan oleh frontend developer karena beralih ke vuejs atau reactjs, namun saya tertarik membahasnya di tulisan pendek ini.

Continue reading Blade Error Directive Pada Laravel 5.8.13

Laravel: Unit Testing dengan SQLite Memory

Lama tidak menulis artikel, hari ini coba untuk membahas tulisan sederhana bagaimana kita membuat unit testing di Laravel dengan menggunakan SQLite di dalam memory. Kenapa harus membuat unit testing? kenapa harus menyimpannya pada SQLite? dan kenapa menggunakan memory? Yuk kita bahas satu per satu ya.

Kenapa membuat Unit Testing?

Sebagai developer atau programmer, kita tentu diharapkan dapat membuat aplikasi yang minim error. Bagaimana agar minim error? tentu kita harus mengenal apa itu error dan bagaimana error itu bisa muncul. Ketika error sudah kita kenali, kita buat kode untuk menghindari error tersebut.

Pekerjaan ini tentu memakan waktu kita sebagai developer yang biasa membuat aplikasi, lalu test dan deliver ke pengguna. Apa ada pembaca disini yang membuat aplikasi lalu langsung di deliver ke pengguna? 😀 Jangan ya..

Di proses test yang biasanya kita lakukan secara manual, sekarang kita ubah proses itu dengan cara membuat unit testing / kode kecil untuk melakukan testing. Kode-kode tersebut akan dijalankan sebelum proses deploy (aplikasi siap digunakan oleh user). Jadi sebelum user menggunakan aplikasi yang kita buat, kita (programmer) pantau terlebih dahulu proses testing ini.

Bagaimana jika flow aplikasi berubah?

Jika aplikasi berubah, kita harus ubah juga kode unit testing sesuai dengan perubahan tersebut. Ini tentunya menambah pekerjaan lagi buat programmer ya. Tapi langkah ini diambil untuk memastikan produk kita sesuai dengan rencana dan meminimalisir error yang muncul.

Kenapa menggunakan SQLite untuk Unit Testing?

Sebelum membahas kenapa menggunakan SQLite, pastikan kita sudah mengetahui apa itu SQLite dan manfaat SQLite dalam database di aplikasi kita. SQLite biasanya digunakan untuk menyimpan data secara local di lingkungan aplikasi dengan beberapa keterbatasan dan kelebihan yang ada pada SQLite. Saya tidak akan membahas jauh tentang SQLite ya.

Alasan kenapa menggunakan SQLite untuk unit testing adalah untuk memudahkan kita melakukan testing yang berkaitan dengan database. Ketika kita programmer sudah bekerja bersama programmer lain, kita kadang tidak mungkin memiliki database dengan data yang sama.

Ada beberapa programmer yang sedang mengerjakan feature tertentu dengan data di database yang mungkin berbeda. Namun perlu diingat, pada suatu waktu pasti feature dari tiap programmer akan disatukan dalam satu kode yang sama sehingga tiap-tiap programmer harus memiliki data yang sama persis. Ketika itu terjadi, tentu saja proses testing juga tetap harus berjalan.

Lalu kenapa tidak menggunakan MySQL? Atau RDBMS Lainnya?

Awalnya saya juga menggunakan MySQL karena aplikasi yang sedang berjalan juga menggunakan MySQL. Namun setelah mencari informasi jika kita menggunakan SQLite itu lebih kecil dan lebih cepat melakukan testing dengan data yang sama. Kadang beberapa unit kecil testing flow yang kita tulis hanya beberapa proses kecil yang juga bisa dilakukan dengan SQLite.

Dengan keterbatasan SQLite, temen-temen juga perlu memperhatikan itu ketika melakukan testing jangan sampai ada query atau data atau mungkin join table yang terbatasi oleh SQLite. Beberapa batasan dari SQLite ini bisa temen-temen lihat di link berikut ini: https://www.sqlite.org/limits.html

Apa maksud SQLite dengan Memory?

Kalau temen-temen pernah menggunakan SQlite, kita tentu store atau simpan data di salah satu file di hardisk atau storage. Nah SQLite ini juga bisa menyimpan tanpa file di storage, kita bisa simpan itu di memory. Mungkin ada yang kepikiran seperti redis ya, eh wait, ada yang belum tahu apa itu redis? Silahkan baca tulisan sederhana saya tentang redis di sini: https://www.adiputra.web.id/mengenal-redis-teori-sederhana/

Temen-temen bisa baca dokumentasi SQLite dengan Memory di link berikut ini: https://www.sqlite.org/inmemorydb.html

Dengan adanya memory ini, tentu akan lebih mempercepat proses testing karena unit testing yang kita lakukan mengolah data dimana data itu berada di memory.

Setting SQLite Memory pada Unit Testing Laravel

Setelah kita ketahui beberapa info diatas, yuk sekarang kita coba untuk membuat unit testing sederhana di Laravel. Saya ingin mencoba membuat unit testing untuk CRUD Kupon. Sebelumnya pastikan juga temen-temen sudah menginstall SQLite ya. Yang diperlukan pada proses ini adalah:

  1. Membuat migration table
  2. Membuat factory dengan Faker
  3. Melakukan Setting pada PHPUnit
  4. Membuat unit testing
  5. Jalankan testing

Membuat Migration Table

Sebelum memulai, tentunya pasti kita install laravel di komputer kita ya, jangan komputer orang lain apalagi komputer mantan #eh #becanda

Buat migration table, saya ingin membuat migration table kupon seperti berikut ini:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCouponsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('coupon', function (Blueprint $table) {
            $table->increments('coupon_id');
            $table->unsignedInteger('shop_id')->index();
            $table->string('coupon_name',45)->index();
            $table->tinyInteger('coupon_type');
            $table->string('coupon_code',45)->index();
            $table->decimal('coupon_amount');
            $table->decimal('coupon_minpurchase');
            $table->date('coupon_expire')->nullable();
            $table->date('coupon_start')->nullable();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('coupon');
    }
}

Ada yang bertanya mungkin kenapa kita ingin membuat unit testing tapi harus membuat migration dulu?

Kalau temen-temen ingin membuat unit testing tanpa data yaa tidak perlu ada migration. Migration disini berguna untuk menyetting struktur table di SQLite yang kita buat nanti. Jadi tanpa migration, unit testing kita akan selalu gagal karena struktur table tidak ditemukan 🙂

Membuat Factory dengan Faker

Ada yang belum mengerti Factory di Laravel? mudah-mudahan sudah mengerti ya. Gunanya membuat Factory di Laravel adalah agar kita bisa meng-generate data dengan mudah di struktur table yang sebelumnya kita buat dengan migration. Factory ini akan kita panggil nanti di unit testing yang akan kita buat. Jika ada temen-temen yang ingin membaca apa itu factory mungkin bisa baca dokumentasi pada Laravel disini: https://laravel.com/docs/5.8/database-testing#generating-factories

Faker sendiri adalah salah satu package yang memudahkan kita mengisi data yang mirip dengan keadaan kolom. Karena kita diatas membahas factory dimana data akan di generate. Tentu saja generate tersebut tidak secara otomatis. Kita harus isi data tersebut lalu proses pengisian biasanya kita lakukan dengan memanggil method random yang ada pada PHP ataupun Helper di Laravel. Nah dengan Faker, kita bisa mengisi data yang mirip dengan kondisi dari kolom data. Misalnya data kolom nomor telp secara random, data kolom nama secara random, data kolom email secara random.

Temen-temen yang ingin lihat package Faker ini bisa lihat disini tanpa harus gugel: https://github.com/fzaninotto/Faker

Lalu berikut adalah factory yang saya buat dengan nama CouponFactory.php:

<?php

use Faker\Generator as Faker;

$factory->define(App\Models\Coupon::class, function (Faker $faker) {

    $coupon_ongoing = $faker->randomElement(array(0,1));
    $coupon_start = null;
    $coupon_expire = null;

    if($coupon_ongoing == 0) {
        $start = $faker->dateTimeBetween('+1 days', '+90 days');

        $coupon_start = $start->format('Y-m-d');
        $coupon_expire = $faker->dateTimeBetween($start, $start->format('Y-m-d H:i:s') . '+60 days')->format('Y-m-d');
    }

    return [
        'coupon_id' => $faker->randomDigit,
        'shop_id' => $faker->randomDigit,
        'coupon_name' => $faker->name,
        'coupon_code' => $faker->name,
        'coupon_type' => $faker->randomElement(array(1,2)),
        'coupon_amount' => $faker->randomDigit,
        'coupon_quantity' => $faker->randomDigit,
        'coupon_minpurchase' => $faker->randomDigit,
        'coupon_start' => $coupon_start,
        'coupon_expire' => $coupon_expire
    ];
});

Melakukan Setting pada PHPUnit

Setelah kita membuat Factory, sekarang kita setting di PHPUnit. PHPUnit adalah package yang memudahkan kita melakukan proses testing. Ada beberapa method bawaan dari PHPUnit yang memudahkan kita untuk mengecek data, atau kondis dari flow aplikasi yang kita buat.

Laravel sendiri sudah secara default mengikutsertakan PHPUnit di framework ini. Dalam artian, temen-temen tidak perlu menginstall package atau data ketika menggunakan PHPUnit ini. Yang perlu temen-temen lakukan adalah tambahkan data pada file phpunit.xml dengan tag default seperti ini (pada laravel 5.7)

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="vendor/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>

        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
        </whitelist>
    </filter>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="BCRYPT_ROUNDS" value="4"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_DRIVER" value="sync"/>
        <env name="MAIL_DRIVER" value="array"/>
    </php>
</phpunit>

Menjadi seperti ini:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="vendor/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>

        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
        </whitelist>
    </filter>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_DRIVER" value="sync"/>
        <env name="MAIL_DRIVER" value="array"/>
        <env name="DB_CONNECTION" value="sqlite"/>
        <env name="DB_DATABASE" value=":memory:"/>
    </php>
</phpunit>

Kalau temen-temen lihat, yang utama adalah penambahan key name DB_CONNECTION = sqlite dan DB_DATABASE = :memory:

Kedua tambahan key name tersebut untuk menyetting database connection dan db name kita saat melakukan testing.

Laravel otomatis akan membaca data yang ada pada phpunit.xml ketika kita melakukan test. Temen-temen juga bisa menggunakan file .env.testing jika mau dan perlu beberapa setting ya.

Membuat Unit Testing

Setelah itu, sekarang kita coba membuat unit testing coupon untuk mendapatkan list seperti kode berikut ini:

<?php
namespace Tests\Feature\V3;

use App\Models\Shop;
use App\Models\User;
use App\Models\Coupon;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
use Laravel\Passport\Passport;

class CouponTest extends TestCase
{
    use RefreshDatabase;

    public function setUp()
    {
        parent::setUp();
    }

    /**
     * @test
     */
    public function user_want_get_resource_coupon_list()
    {
        Passport::actingAs(
            factory(User::class)->create(),
            ['all'],
            'api'
        );
        
        $this->shop = factory(Shop::class)->create();

        factory(Coupon::class)->create([
            'shop_id' => $this->shop->shop_id
        ]);

        $response = $this->get('/api/shop/' . $this->shop->shop_id . '/coupon');

        $response
            ->assertSuccessful()
            ->assertSee('shop_id')
            ->assertSee('coupon_name')
            ->assertSee('coupon_code');
    }

}

Jika temen-temen lihat diatas, saya memanggil factory Coupon::class yang telah kita buat sebelumnya. Lalu ada beberapa factory lain seperti factory User dan Shop yang tidak saya bahas.

Intinya dari kode unit testing diatas adalah, kita membuat data dengan factory coupon, setelah data dibuat maka tentu akan masuk ke SQLite Memory. Dan setelah itu kita coba panggil API Restful untuk menghandle data list coupon yang kita baru saja buat.

Kode Controller dan Route untuk menghandle data API Restful tidak saya tulis disini. Saya hanya menjelaskan flow ketika kita menggunakan SQLite Memory pada Unit testing yang kita buat.

Sampai disini, kritik saran atau ada yang tidak sesuai, boleh komentar di kolom komentar ya. Saya juga masih belajar 🙂

Belajar PHP Mencoba RatchetPHP untuk menangani Websocket

RatchetPHP library dapat membantu kita untuk membuat websocket, realtime aplikasi. Websocket sendiri kadang diperlukan di beberapa kasus aplikasi yang menginginkan data dan flow proses dilakukan secara realtime. Contoh sederhana adalah kita sedang chatting, ada proses yang dilakukan secara realtime.

Kasus ini sebenarnya sudah dikenalkan di salah satu fitur keren dari NodeJS. Dengan NodeJS kita dapat mudah melakukan hal tersebut dengan bahasa Javascript. Namun, mungkin ada beberapa kasus dimana kita tidak bisa menggunakan JS untuk menghandle proses websocket ini dan harus menggunakan PHP karena mungkin semua aplikasi dibagun di atas PHP.

Saya mencoba mengikuti dokumentasi dari RatchetPHP dan mengikuti beberapa tutorial yang ada di internet. Berikut saya coba tulis di blog agar nanti bisa mudah di implementasikan kembali tanpa harus browsing-browsing lagi.

Tahapan-nya:
1. PHP versi 7
Versi PHP yang bisa menjalankan Ratchetphp ini >=5.4.2. Untuk temen-temen yang masih dibawah itu belum bisa menggunakan RatchetPHP ini. Saya sarankan menggunakan PHP Versi 7+
2. Install ZeroMQ. Distributed system message.
Ini seperti RabbitMQ yang gunanya menghantarkan data/message. Karena RatchetPHP ini menggunakan ZeroMQ, saya mengikuti untuk memasang ZeroMQ di ubuntu saya. Panduan Installasi bisa mengikut di link ini: https://gist.github.com/katopz/8b766a5cb0ca96c816658e9407e83d00

#!/usr/bin/bash

# Download zeromq
# Ref http://zeromq.org/intro:get-the-software
wget https://github.com/zeromq/libzmq/releases/download/v4.2.2/zeromq-4.2.2.tar.gz

# Unpack tarball package
tar xvzf zeromq-4.2.2.tar.gz

# Install dependency
sudo apt-get update && \
sudo apt-get install -y libtool pkg-config build-essential autoconf automake uuid-dev

# Create make file
cd zeromq-4.2.2
./configure

# Build and install(root permission only)
sudo make install

# Install zeromq driver on linux
sudo ldconfig

# Check installed
ldconfig -p | grep zmq

# Expected
############################################################
# libzmq.so.5 (libc6,x86-64) => /usr/local/lib/libzmq.so.5
# libzmq.so (libc6,x86-64) => /usr/local/lib/libzmq.so
############################################################


3. Install ext-zmq. extension untuk ZeroMQ.
Extension ini untuk menghubungkan antara PHP dengan ZeroMQ. Temen-temen bisa lihat di link ini https://eole-io.github.io/sandstone-doc/install-zmq-php-linux

Setelah semua di install buat folder berisi composer json seperti berikut ini:

{
    "name": "adiputra/rachetphp-test",
    "description": "rachetphp testing",
    "require": {
        "cboden/ratchet": "^0.4.1",
        "react/zmq": "0.2.*|0.3.*"
    },
    "autoload": {
        "psr-4": {
            "Adiputra\\Rachetphp\\": "src"
        }
    },
    "authors": [
        {
            "name": "Adiputra",
            "email": "tuts.adiputra@gmail.com"
        }
    ]
}

Setelah itu jalankan composer install untuk menginstall beberapa library dari Ratchetphp ini.

Setelah itu kita buat folder src lalu di dalam folder src kita buat folder bin dan file server.php. Isi file server.php seperti berikut ini:

<?php
require dirname(__DIR__) . '../../vendor/autoload.php';

use React\EventLoop\Factory;
use React\ZMQ\Context;

$loop = React\EventLoop\Factory::create();
$broadcast = new Adiputra\Rachetphp\Broadcast;

// Listen for the web server to make a ZeroMQ push after an ajax request
$context = new React\ZMQ\Context($loop);
$pull = $context->getSocket(ZMQ::SOCKET_PULL);
$pull->bind('tcp://127.0.0.1:5555'); // Binding to 127.0.0.1 means the only client that can connect is itself
$pull->on('message', array($broadcast, 'onNewObject'));

// Set up our WebSocket server for clients wanting real-time updates
$webSock = new React\Socket\Server('0.0.0.0:8080', $loop); // Binding to 0.0.0.0 means remotes can connect
$webServer = new Ratchet\Server\IoServer(
    new Ratchet\Http\HttpServer(
        new Ratchet\WebSocket\WsServer(
            $broadcast
        )
    ),
    $webSock
);

$loop->run();

File server.php gunanya untuk membuat server serta melisten atau menerima apakah ada data yang dikirimkan oleh client atau tidak.

Setelah itu kita buat file client yaitu index.html seperti kode dibawah ini:

<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

<div id="messages"></div>

<div>
    <form>
        <input type="text" id="msgText">
        <input type="button" id="msgSend" value=">">
    </form>
</div>
<script>
    var conn = new WebSocket('ws://localhost:8080');
    var userId = 51;
    
    conn.onopen = function (e) {
        console.log("Connection established!");
        console.log(e.data);
    };

    conn.onmessage = function (e) {
        console.log(e.data);

        var response = JSON.parse(e.data);
        if(response['user_id'] == userId) {
            var chat = document.createElement("div");
            var cwind = document.getElementById("messages");
            cwind.appendChild(chat);
            cwind.lastElementChild.innerHTML = response["message"];
        }
    };

    var button = document.getElementById("msgSend");

    button.onclick = function () {
        var val = document.getElementById("msgText").value;
        conn.send(JSON.stringify({'user_id': userId, 'message': val}));
    };

</script>
</body>

File index.html ini adalah file client yang nanti akan menerima data dari server ke client atau sebaliknya dari client ke server.

Setelah itu saya buat file Broadcast.php seperti kode dibawah ini:

<?php
namespace Adiputra\Rachetphp;

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

class Broadcast implements MessageComponentInterface {
    protected $clients;

    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }

    public function onOpen(ConnectionInterface $conn) {
        // Store the new connection to send messages to later
        $this->clients->attach($conn);

        echo "New connection! ({$conn->resourceId})\n";
    }

    public function onMessage(ConnectionInterface $from, $msg) {
        $numRecv = count($this->clients) - 1;
        echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
            , $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');

        foreach ($this->clients as $client) {
            if ($from !== $client) {
                // The sender is not the receiver, send to each client connected
                $client->send($msg);
            }
        }
    }

    public function onClose(ConnectionInterface $conn) {
        // The connection is closed, remove it, as we can no longer send it messages
        $this->clients->detach($conn);

        echo "Connection {$conn->resourceId} has disconnected\n";
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "An error has occurred: {$e->getMessage()}\n";

        $conn->close();
    }

    public function onNewObject($msg)
    {
        echo "on new object fire \n";
        foreach ($this->clients as $client) {
            $client->send($msg);
        }
    }
}

Isi file tersebut adalah membaca beberapa event yang terjadi. Temen-temen yang pernah menggunakan Socket IO pasti memahami beberapa event disini ya. Secara garis besar terdapat event ketika telah terbuka / masuk (on open). Ketika sedang tertutup (on close) dan ketika terjadi pengiriman data (on message). Beberapa method seperti on error untuk menghandle ketika terjadi error pada class Ratchetphp ini. Ke-empat method itu adalah bawaan utama atau default yang saya baca pada documentasi RatchetPHP

Terdapat method tambahan yaitu method onNewObject. Kegunaan method itu untuk mengirimkan kembali ke client data setelah menerima data.

Sampai disini kawan-kawan bisa menjalankan dengan cara:
1. Jalankan server.php
Menjalankan server.php dengan cara mengetikan php src/bin/server.php. Pastikan ketika menjalankan ini tidak memunculkan error.
2. Jalankan index.html di beberapa browser
Untuk menerima dan mengirimkan data dari client ke client lain. Kawan-kawan bisa membuka file index.html di beberapa browser seperti browser firefox dan chromium.

Sampai disini seharusnya sudah jalan dengan baik ya 🙂

Saya coba membuat file baru dengan nama SendMessage.php:

<?php
$userId = 51;

$entryData = array(
    'user_id' => $userId,
    'message' => "Send message for user id: " . $userId
);

$context = new ZMQContext();
$socket = $context->getSocket(ZMQ::SOCKET_PUSH, 'adiputra');
$socket->connect("tcp://localhost:5555");
$socket->send(json_encode($entryData));

File ini gunanya untuk mengakses langsung file PHP lalu mengirimkan data ke socket agar client bisa membaca data yang dikirimkan dengan PHP.

Temen temen bisa mencoba dengan mengetikkan perintah php src/SendMessage.php untuk mencobanya.

Belajar Redis: Tipe data String pada Redis

Tipe data String pada dunia pemrograman sangat banyak digunakan. Redis memiliki juga tipe data String untuk menyimpan data string pada umumnya. Pada Redis, tipe data String ini ada batasannya yaitu 512 MB. Lebih dari itu, kawan-kawan tidak bisa menggunakan tipe data ini ya. (kebayang string sampe lebih dari 512 isinya apa ya? hehe)

Sebelumnya, pastikan ya di komputer kawan-kawan terinstall redis untuk mencoba belajar redis bagian tipe data string pada redis ini.

Perintah SET, GET, MSET, MGET

Lanjut ke perintah apa aja yang bisa dipakai di tipe data String ini pada redis. Kawan-kawan tentu bisa menggunakan perintah SET dan GET pada tipe data string ini. Kawan-kawan juga bisa menggunakan MSET dan MGET pada tipe data String pada redis ini.

Contohnya adalah saya membuat tipe data string dengan MSET dan MGET seperti berikut ini.

redis tipe data string 1

Terlihat pada gambar diatas, awalnya kawan-kawan ketik dulu untuk menjalankan redis yaitu redis-cli. Setelah itu saya ketik perintah MSET lalu diikuti dengan KEY yaitu first dan diikuti dengan value yang berisi tipe data String yaitu “ini kalimat pertama”. Setelah value dari KEY first ini, saya tambahkan juga KEY second dengan value “ini kalimat kedua”. Tekan enter sampai tertulis “OK”.

Setelah itu kawan-kawan bisa mengambil data string yang kita set sebelumnya itu dengan perintah MGET dengan beberapa KEY yang telah dibuat. Misalnya saya tulis “MGET first second”. Ketika di enter akan muncul value dari KEY ‘first’ dan KEY ‘second’. Kawan-kawan juga bisa memanggil dengan perintah single GET KEY seperti memanggil dengan GET first atau GET second.

Sesuai dengan namanya MGET dan MSET artinya adalah Multiple GET dan Multiple SET. Kawan-kawan bisa set multiple key dengan MSET dan get multiple key dengan MGET.

Perintah STRLEN

Untuk menghitung jumlah panjang value pada key tertentu, kawan-kawan bisa menggunakan STRLEN. Contohnya bisa seperti berikut:

127.0.0.1:6379> MGET first second
1) "ini kalimat pertama"
2) "ini kalimat kedua"
127.0.0.1:6379> STRLEN first
(integer) 19

Terlihat pada kode diatas, saya panggil STRLEN first. dimana first adalah key dari value “ini kalimat pertama”. Lalu jika dihitung ada 19 karakter ya 🙂

Perintah SETEX

Kawan-kawan juga bisa menggunakan SETEX. Perintah SETEX pada redis digunakan untuk menge-set value tertentu dengan syarat akan hilang dalam detik yang ditentukan.

SETEX redis

Pada gambar diatas, saya coba set key “kopi” dengan expired time dalam detik yaitu 20 detik lalu diikuti value dari key yang inginkan. Ketika saya panggil GET berkali-kali masih muncul, namun setelah lebih dari 20 detik akan hilang (nil) dari memory. Jadi itulah perintah SETEX pada redis.

Perintah DEL

Setelah kita belajar GET dan SET serta multiplenya, tanpa waktu expired, kita bisa langsung menghapus nilai dari key tertentu. Caranya bagaimana? nah kita bisa menggunakan perintah DEL pada redis.

Perintah DEL Redis

Kawan-kawan bisa lihat saya set key ‘nama’ dengan value ‘adiputra’. Lalu saya coba delete dengan perintah del sebanyak 2 kali. Pada perintah pertama akan mengeluarkan nilai 1, itu tanda proses delete berhasil. Pada perintah kedua mengeluarkan nilai 0 menjadi tanda proses delete gagal. Kenapa bisa gagal? Bener…datanya diawal kan sudah hilang ya..:)

Penasaran masih gak percaya itu sudah dihapus? kawan-kawan bisa panggil dengan perintah GET nama. Apa masih muncul? keluar nil ya 😀

Perintah GETSET

Perintah yang sering dilakukan di tipe data string atau juga tipe data lain adalah perintah GETSET. Apa arti perintah GETSET itu ya? Secara sederhana ini adalah proses update value dari key yang ingin kita update. Misalnya gini, kawan-kawan pertama set key ‘nama’ dengan value ‘adiputra’, lalu kawan-kawan ingin mengganti key ‘nama’ menjadi value ‘anas’. Apa yang kawan-kawan lakukan?

Yap, delete key nama, buat key nama baru. Nah dengan perintah GETSET ini, kawan-kawan tidak perlu menghapus key tersebut. Kawan-kawan bisa langsung meng-update data key tersebut dengan perintah GETSET ini.

Perintah GETSET Redis

Jika kawan-kawan lihat gambar diatas, terlihat saya set nama dengan value adiputra, lalu saya getset nama menjadi anas. Terlihat saat GETSET nama anas ada keluaran nama “adiputra” ya. Redis mengeluarkan nilai yang telah di update namun data yang baru akan disimpan pada key ‘nama’. Jika kawan-kawan lihat kembali gambar diatas, Saya ketik GET nama mengeluarkan nilai ‘anas’.

Tanpa perlu menghapus key, kita bisa langsung meng-update nilai key tersebut. Keren!

Kawan-kawan mungkin ada yang bertanya, bagaimana jika memang GETSET key tersebut dalam keadaan key belum ada pada redis? Nah tetep akan meng-set key terbaru dengan value terbaru walaupun key belum ada di redis.

Perintah GETSET jika kosong

Terlihat pada gambar diatas, saya coba GETSET pada key yang kosong pada redis maka mengeluarkan nilai nil, namun tetep ketika kita panggil GET akan mengeluarkan nilai terbaru yang kita set yaitu ‘budi’.

Perintah SETNX

Salah satu perintah menarik lagi yaitu perintah SETNX.

[berlanjut]

Belajar PHP – Menggunakan array_unique

Seri belajar PHP hari ini adalah bagaimana kita menggunakan array_unique pada PHP. Pada kasus tertentu kita mendapatkan data yang berasal baik itu dari database atau user input pada form yang telah kita sediakan, namun memiliki nilai yang duplicate atau bisa disebut sama. Untuk menghindari data yang kita kelola itu duplikat, pada PHP kita bisa menggunakan array_unique ini.

Pada dokumentasi PHP, array unique ini sudah ada pada versi PHP4 dan pada Versi PHP 7 masih bisa kita gunakan lho.

array_unique ini digunakan untuk menghindari duplikat dari nilai sebuah array.

array_unique ( array $array [, int $sort_flags = SORT_STRING ] )

Fungsi array_unique ini juga mengeluarkan nilai yang unique pada array sehingga kita bisa membuat variable baru untuk memisahkan antara variable yang duplikat dengan variable yang sudah unique.

<?php
$input = array(1,2,"1",3,"3","5",5,1);
$result = array_unique($input);
print_r($result);
?>

Hasil dari kode diatas seperti ini.

Array
(
    [0] => 1
    [1] => 2
    [3] => 3
    [5] => 5
)

Bisa kawan-kawan lihat, hasil mengeluarkan nilai yang unique.

Kawan-kawan juga bisa lihat array_unique ini juga bisa membandingkan tipe integer dan string ya. Lalu keluaran dari array_unique ini mengeluarkan key dimana array value itu berasal, maksudnya key 0 => 1, key 1 => 2, key 3 => 3 dan seterusnya. Jadi output tidak selalu berurutan.

array_unique ini belum bisa melakukan proses pada array multiple. Sebagai contoh berikut ini.

<?php
$input = [
    0 => [
        "id" => 1,
        "value" => "nilai 1"
    ],
    1 => [
        "id" => 2,
        "value" => "nilai 2"
    ],
    2 => [
        "id" => 3,
        "value" => "nilai 3"
    ],
    3 => [
        "id" => 4,
        "value" => "nilai 2"
    ]
];

$result = array_unique($input);
var_dump($result);
?>

Jika kawan-kawan menjalankan kode berikut, akan muncul error seperti ini.

<br />
<b>Notice</b>:  Array to string conversion in <b>[...][...]</b> on line <b>21</b><br />
<br />
<b>Notice</b>:  Array to string conversion in <b>[...][...]</b> on line <b>21</b><br />
<br />
<b>Notice</b>:  Array to string conversion in <b>[...][...]</b> on line <b>21</b><br />
<br />
<b>Notice</b>:  Array to string conversion in <b>[...][...]</b> on line <b>21</b><br />
<br />
<b>Notice</b>:  Array to string conversion in <b>[...][...]</b> on line <b>21</b><br />
<br />
<b>Notice</b>:  Array to string conversion in <b>[...][...]</b> on line <b>21</b><br />
<br />
<b>Notice</b>:  Array to string conversion in <b>[...][...]</b> on line <b>21</b><br />
<br />
<b>Notice</b>:  Array to string conversion in <b>[...][...]</b> on line <b>21</b><br />
<br />
<b>Notice</b>:  Array to string conversion in <b>[...][...]</b> on line <b>21</b><br />
<br />
<b>Notice</b>:  Array to string conversion in <b>[...][...]</b> on line <b>21</b><br />
<br />
<b>Notice</b>:  Array to string conversion in <b>[...][...]</b> on line <b>21</b><br />
<br />
<b>Notice</b>:  Array to string conversion in <b>[...][...]</b> on line <b>21</b><br />
array(1) {
  [0]=>
  array(2) {
    ["id"]=>
    int(1)
    ["value"]=>
    string(7) "nilai 1"
  }
}

Error tersebut karena array_unique berusaha untuk mengkonversi nilai array menjadi sebuah string namun ternyata nilai adalah array. Sehingga muncullah error seperti itu.

Lalu bagaimana cara agar value “nilai 2” ini tidak duplikat?

Ada beberapa cara, salah satunya kita gunakan array_column sehingga menjadi seperti berikut ini.

<?php
$input = [
    0 => [
        "id" => 1,
        "value" => "nilai 1"
    ],
    1 => [
        "id" => 2,
        "value" => "nilai 2"
    ],
    2 => [
        "id" => 3,
        "value" => "nilai 3"
    ],
    3 => [
        "id" => 4,
        "value" => "nilai 2"
    ]
];

$result = array_unique(array_column($input, 'value'));
var_dump($result);
?>

keluaran akan menjadi seperti berikut:

array(3) {
  [0]=>
  string(7) "nilai 1"
  [1]=>
  string(7) "nilai 2"
  [2]=>
  string(7) "nilai 3"
}

Sesuai dengan yang kita mau ya, karena fungsi array_column adalah mengambil multiple array menjadi satu array dengan menginputkan key yang ingin dikeluarkan. Jika kawan-kawan mencoba tanpa array_unique akan seperti ini.

<?php
$input = [
    0 => [
        "id" => 1,
        "value" => "nilai 1"
    ],
    1 => [
        "id" => 2,
        "value" => "nilai 2"
    ],
    2 => [
        "id" => 3,
        "value" => "nilai 3"
    ],
    3 => [
        "id" => 4,
        "value" => "nilai 2"
    ]
];

$result = array_column($input, 'value');
var_dump($result);
?>

// result
array(4) {
  [0]=>
  string(7) "nilai 1"
  [1]=>
  string(7) "nilai 2"
  [2]=>
  string(7) "nilai 3"
  [3]=>
  string(7) "nilai 2"
}

Sampai disini, mudah-mudahan bermanfaat untuk seri belajar php array unique 😉

 

 

Belajar ES6 – Perubahan Object Literal

Salah satu fitur lagi pada ES6 yang banyak digunakan oleh beberapa framework seperti ReactJS, Angular dan VueJS adalah perubahan pada Object Literal. Pertama kali saya ketika melihat tutorial dari VueJS ataupun ReactJS agak bingung. Kok itu membuat fungsi di objectnya lain yaa…kok itu passing variable ke object beda ya..garuk2 gak ngerti..Ternyata itu fitur dari ES6 yaitu Object Literal.

Continue reading Belajar ES6 – Perubahan Object Literal