Membuat Fungsi Berantai (Chained Method/Function) di PHP


Di Laravel versi 5.x, kita sering menemui beberapa fungsi yang berperan sebagai alias dari suatu method pada sebuah class. Semisal, untuk memuat view, kita bisa menggunakan facade View::make($view, $data), cara singkatnya bisa menggunakan fungsi view($view, $data). Atau, contoh lain misalnya, jika biasa menggunakan facade Redirect::to($url), maka untuk lebih sederhana jika menggunakan redirect($url).

Kalau kita buka source code-nya, dapat dipahami kalau fungsi tersebut pada dasarnya menggunakan class yang sama dengan facade di atas. Misal pada fungsi view() berikut:

if (! function_exists('view')) {
    /**
     * Get the evaluated view contents for the given view.
     *
     * @param  string  $view
     * @param  array   $data
     * @param  array   $mergeData
     * @return \Illuminate\View\View|\Illuminate\Contracts\View\Factory
     */
    function view($view = null, $data = [], $mergeData = [])
    {
        $factory = app(ViewFactory::class);
 
        if (func_num_args() === 0) {
            return $factory;
        }
 
        return $factory->make($view, $data, $mergeData);
    }
}

Selain itu, kita juga bisa menggunakan fungsi berantai (chained method/function) pada fungsi sederhana yang telah digunakan. Sebagai contoh, jika kita menggunakan facade Redirect::to($url)->with($type, $message), maka untuk cara yang lebih sederhana bisa menggunakan fungsi redirect($url)->with($type, $mssage).

Nah untuk pengetahuan tambahan, kita juga bisa membuat kode agar bekerja layaknya seperti beberapa kode di atas, yaitu membuat sebuah fungsi sebagai alias dari class dan membuat fungsi berantai berdasarkan class tersebut.

How To

Karena misi kali ini adalah membuat fungsi alias dari sebuah class dan fungsi berantai, maka syarat utamanya tentu saja harus membuat sebuah class terlebih dahulu. Sebagai contoh, kali ini kita akan membuat class dengan nama User dan disimpan dalam format PHP dengan nama Chained.php.

Sebelum masuk lebih jauh ke dalam pembahasan, saya sarankan untuk memperdalam pemahaman mengenai class dan object di PHP.
Sebagai gambaran kasar, class di bawah berfungsi untuk menyetel nama dan email user, kemudian mengambalikan nilai berupa string dengan format JSON.

<?php 
 
/**
 * Simple chained method in PHP
 *
 * @author Yugo <dedy.yugo.purwanto@gmail.com>
 * @copyright 2016
 */
class User {
 
    /**
     * User Name
     *      
     * @var string
     */
    private $name = null;
 
    /**
     * User Email
     * 
     * @var string
     */
    private $email = null;
 
    public function __construct($data = null)
    {
        // set default data
        if (! empty($data)) {
            foreach ($data as $key => $value) {
                if (property_exists($this, $key)) {
                    $this->$key = $value;
                }
            }
        }
    }
 
    /**
     * Set default name
     * 
     * @param string $name
         * @return object
     */
    public function setName($name)
    {
        $this->name = $name;
        return $this;
    }
 
    /**
     * Set default email
     * 
     * @param object $email
         * @return object
     */
    public function setEmail($email) 
    {
        $this->email = $email;
        return $this;
    }
 
    /**
     * Return as JSON formatted string
     * 
     * @return string
     */
    public function json()
    {
        return json_encode([
            'name' => $this->name,
            'email' => $this->email
        ]);
    }
}
 
// simple function
function user($user = null) {
    return new User($user);
}

Selain membuat class User, pada potongan kode di atas juga terdapat baris untuk mendefinisikan fungsi baru dengan nama user(). Fungsi ini akan mengembalikan object dari class User. Dengan begitu, method yang ada pada class User juga dapat digunakan pada fungsi user(). Sebagai pembanding, coba lihat implementasinya pada kode di bawah.

// instance class
$user = new User;
echo $user->setName('Laravel.web.id')
    ->setEmail('mail@laravel.web.id')
    ->json();
 
// simpler class instance
echo (new User)->setName('Laravel.web.id')->setEmail('mail@laravel.web.id')->json();
 
// simple function
echo user()->setName('Laravel.web.id')
    ->setEmail('mail@laravel.web.id')
    ->json();
 
// simple function with __construct
echo user(['name' => 'Laravel.web.id', 'email' => 'mail@laravel.web.id'])->json();
 
// semuanya akan menampilkan string kurang lebih seperti berikut
{"name":"Laravel.web.id","email":"mail@laravel.web.id"}

But, Wait!

Seringkali kita melihat sebuah fungsi (yang merupakan instance dari sebuah class) mengembalikan nilai string, tapi akan berperilaku sebagai object ketika disambungkan dengan fungsi lainnya. Semisal, fungsi user() akan mengembalikan nilai string, tapi fungsi user()->setName() akan mengembalikan nilai berupa object.

echo user('Laravel');
 
// menghasilkan pesan kesalahan berikut
Catchable fatal error: Object of class User could not be converted to string in ...

Jadi, semenjak versi 5.2, PHP memperkenalkan keluarga baru magic method bernama __toString(). Method ini dapat digunakan untuk menangani kasus ketika object suatu class ditampilkan secara langsung menggunakan echo atau print(). Agar dapat berfungsi sesuai kehendak, mari kita modifikasi class User dari berkas Chained.php dengan menambahkan method __toString().

/**
 * Return data as JSON formatted using json() method
 * 
 * @return string
 */
public function __toString()
{
    // menggunakan method yang sudah ada
    return $this->json();
}

Untuk mengujinya, cobalah untuk menampilkan object tersebut menggunakan echo.

$user = new User(['name' => 'Laravel.web.id', 'email' => 'mail@laravel.web.id']);
echo $user;

Atau bisa juga dengan menggunakan fungsi sederhana yang telah dibuat sebelumnya.

$data = ['name' => 'Laravel.web.id', 'email' => 'mail@laravel.web.id']);
 
echo user($data);
 
// apakah ada perbedaanya jika menggunakan kode di bawah?
 
echo user($data)->json();

Terakhir, yang perlu diperhatikan, bahwa method setName() dan setEmail() mengembalikan object class tersebut, sedangkan method json() mengembalikan nilai berupa string. Maka dari itu, ketika pemanggilan, method json() harus berada pada akhir dari rantai untuk menghindari fatal error dari PHP.

// simple function
echo user()->setName('Laravel.web.id')
    ->json()
    ->setEmail('mail@laravel.web.id');
 
// akan menghasilkan
Fatal error: Uncaught Error: Call to a member function setEmail() on string in ...

Kode lengkap artikel kali ini dapat dilihat pada Gist Github.

Tak Berkategori

Yugo Purwanto

Pemrogram PHP dan JavaScript yang sedang sibuk mengembangkan aplikasi Glosarium Bahasa Indonesia.

Tinggalkan Balasan