Memahami IoC Container Dan Facade Di Laravel


Sebagai seorang yang datang dari dunia Java, bicara soal IoC Container (Inversion of Control Container), yang muncul dalam bayangan saya adalah Spring Container. Secara sederhana, IoC Container adalah sesuatu yang menyiapkan instance dari class yang ada dan memberikannya pada yang dibutuhkan. Jadi, developer tidak perlu report dengan perintah new. Ia juga tidak perlu ragu lagi apakah object yang sudah ada sebelumnya dapat dipakai ulang. IoC Container akan memberikan object pada class yang dibutuhkan melalui beberapa cara, misalnya service locator (pengguna meminta object tersebut secara manual) atau dependency injection (object disuntik secara otomatis pada penggunanya).

Untuk menunjukkan penggunaan IoC Container di Laravel 4, saya akan membuat sebuah class service sederhana yang mengembalikan nomor faktur berurut seperti ‘FA-2014/05-00001’:

<?php

namespace services;

use DB, Log;

class NomorService {

    private $nomorTerakhir;

    function __construct() {
        Log::debug('Melakukan query ke database untuk mencari nomor terakhir...');
        $hasil = DB::select('SELECT nomorFaktur FROM faktur WHERE ' . 
            'SUBSTRING(nomorFaktur, 4, 4) = YEAR(CURDATE()) AND '.    
            'SUBSTRING(nomorFaktur, 9, 2) = MONTH(CURDATE()) ' .
            'ORDER BY nomorFaktur DESC LIMIT 1');
        if (empty($hasil)) {
            $this->nomorTerakhir = 0;
        } else {            
            $this->nomorTerakhir = substr($hasil[0]->nomorFaktur, 11);            
        }
    }

    public function getCalonNomor() {       
        return sprintf('FA-%s/%s-%05d', date('Y'), date('m'), $this->nomorTerakhir + 1);
    }
}

?>

Tanpa IoC Container, setiap kali saya akan menggunakan class di atas, saya perlu membuat instance baru darinya seperti pada contoh berikut ini:

<?php

use services\NomorService;

class LatihanController extends BaseController {

    public function getNomorFaktur() {
        $nomorService = new NomorService();
        return $nomorService->getCalonNomor();
    }

}

?>

Cara ini dianggap kurang rapi karena setiap kali membutuhkan NomorService, kode program saya (di controller) memiliki tanggung jawab untuk membuat instance baru dari class tersebut. Hal ini dapat dihindari bila memakai IoC Controller, misalnya dengan constructor injection seperti berikut ini:

<?php

use services\NomorService;

class LatihanController extends BaseController {

    public function __construct(NomorService $nomorService) {
        $this->nomorService = $nomorService;
    }

    public function getNomorFaktur() {      
        return $this->nomorService->getCalonNomor();
    }

}

?>

Pada versi yang memakai constructor injection, IoC Container dari Laravel akan membuat instance baru dari NomorService secara otomatis dan melewatkannya pada constructor. Cara ini jauh lebih baik karena controller tidak punya tanggung jawab untuk membuat services.

Sedikit permasalahan pada kode di atas adalah instance NomorService selalu dibuat setiap kali LatihanController dipanggil. Hal ini biasanya tidak jadi masalah karena pada PHP, setiap kali terdapat request baru, seluruh object selalu dibuat ulang dari awal sehingga static (singleton) tidak begitu banyak berguna. Walaupun demikian, Laravel memungkinkan untuk selalu menyuntikkan instance yang sama (tanpa membuat baru). Ini adalah perilaku default untuk Spring Container karena pada Java, object yang masih dipakai (terutama yang static) tetap dipertahankan di memori walaupun sudah berganti request sehingga terlalu sering membuat objek baru akan boros memori. Agar IoC Container dari Laravel selalu menyuntikkan instance yang sama, saya dapat menambahkan kode program seperti berikut ini di global.php:

App::singleton('services\NomorService', function() { return new \services\NomorService; });
App::make('services\NomorService');

Alternatif lain yang lebih rapi adalah dengan membuat sebuah service provider yang bertugas khusus untuk mendaftarkan NomorService. Sebagai contoh, saya dapat membuat service provider seperti berikut ini:

<?php

namespace services;

use Illuminate\Support\ServiceProvider;

class NomorServiceProvider extends ServiceProvider {

    public function register() {        
        $this->app->singleton('services\NomorService', function() {
            return new NomorService();
        });     
    }   

}

?>

Kemudian, saya perlu mendaftarkan service provider di atas dengan mengubah file config\app.php dengan menambahkan baris seperti berikut ini:

'providers' => array(

    ...
    'services\NomorServiceProvider'

),

Fasilitas lain dari Laravel yang berhubungan dengan IoC adalah facade. Sebuah facade adalah cara singkat untuk memakai object yang ada dalam bentuk class yang berisi method static. Laravel memiliki banyak facade bawaan, misalnya App untuk mewakili Illuminate\Foundation\Application, DB untuk mewakili Illuminate\Database\DatabaseManager, Log untuk mewakili Illuminate\Log\Writer, dan sebagainya.

Sebagai latihan, saya akan membuat facade sehingga obyek NomorService dapat dipakai secara lebih mudah. Untuk itu, saya perlu membuat sebuah class yang diturunkan dari Facade seperti berikut ini:

<?php

namespace services;

use Illuminate\Support\Facades\Facade;

class Nomor extends Facade {

    protected static function getFacadeAccessor() {
        return 'services\NomorService';
    }

}

?>

Saya juga bisa memberikan alias pada facade ini dengan menambah nilai aliases di app/config/app.php seperti berikut ini:

'aliases' => array(
    ...
    'Nomor'           => 'services\Nomor'
),

Setelah ini, saya dapat memanggil NomorService kapan saja dan dimana saja dengan kode program seperti berikut ini:

print Nomor::getCalonNomor();

Perihal Solid Snake
I'm nothing...

5 Responses to Memahami IoC Container Dan Facade Di Laravel

  1. Habib Nurrahman mengatakan:

    Alhamdulillah saya sudah baca artikel ini dan saya sudah lebih mendapatkan pencerahan, hanya saja saya masih bingung dengan bedanya Class ServiceProvider dengan Class Facade apa bedanya kalo sama-sama membuat menjadi static method?

    • Solid Snake mengatakan:

      Service provider yang saya buat disini tidak memiliki static method. Tugasnya hanya mendaftarkan object. Selain itu, ia juga tidak dapat diakses secara langsung, misalnya di controller. Walaupun demikian, saya dapat mengakses object yang didaftarkan oleh si service provider tersebut melalui constructor injection (otomatis) atau melalui facade (static methods).

      Beda service provider dan facade? Facade hanyalah sebuah ‘shortcut’ untuk memanggil instance di app secara cepat, cukup melalui static methods. Service provider hanyalah ‘shortcut’ agar tidak perlu mendaftarkan instance satu per satu di global.php (pembuat Laravel menganggap ini lebih rapi dan lebih mudah diuji).

  2. eezhal92 mengatakan:

    Penjelasannya bagus. salam kenal🙂

  3. Rochmad Arifin mengatakan:

    mas minta tutorialnya yang lebih mudah , bisa? saya bingung buat kode otomatis faktur.. saya masih bingung ioc.. tolong kasih tau step by stepnya

Apa komentar Anda?

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

%d blogger menyukai ini: