Generate UUID Otomatis di Eloquent


Salah satu identifier yang umum digunakan adalah UUID. Panjangnya statis, yaitu 36 karakter, biasanya terdiri dari kombinasi huruf dan angka disertai tanda dash (-).

Ketika menggunakan UUID dalam pangkalan data, bukan berarti kita harus menghilangkan primary key yang bersifat auto-increment (biasanya untuk pangkalan data SQL). Primary key yang bersifat auto-increment bisa saja digunakan dengan UUID secara bersamaan.

Contoh data dan format UUID adalah sebagai berikut:

f5b0e56c-0ee2-45f4-8a61-d5c91be1641d
d69ada29-df29-4b08-937f-14e6fa3471d2
1d8d8de8-600f-46f1-96e4-603af242d94f

A universally unique identifier (UUID) is a 128-bit number used to identify information in computer systems. The term globally unique identifier (GUID) is also used.

Semisal dalam aplikasi, kita menggunakan UUID sebagai key tambahan. Sebut saja kita punya sebuah tabel user yang di dalamnya terdapat kolom UUID dengan nama uuid.

+----------------+------------------+------+-----+---------+----------------+
| Field          | Type             | Null | Key | Default | Extra          |
+----------------+------------------+------+-----+---------+----------------+
| id             | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| uuid           | char(36)         | NO   |     | NULL    |                |
| name           | varchar(191)     | NO   |     | NULL    |                |
| email          | varchar(191)     | NO   | UNI | NULL    |                |
| password       | varchar(191)     | NO   |     | NULL    |                |
| remember_token | varchar(100)     | YES  |     | NULL    |                |
| created_at     | timestamp        | YES  |     | NULL    |                |
| updated_at     | timestamp        | YES  |     | NULL    |                |
+----------------+------------------+------+-----+---------+----------------+

Normalnya, untuk menyimpan nilai UUID tersebut, kita bisa menggunakan potongan skrip di bawah. Dalam contoh, saya menggunakan Faker untuk membuat data.

$faker = Faker\Factory::create('id_ID');

$user = User::create([
    'uuid' => $faker->uuid,
    'name' => $faker->name,
    'email' => $faker->email,
    'password' => bcrypt($faker->password),
]);

Dalam pemrograman sesungguhnya, data dari Faker bisa diambil dari HTTP Request, form misalnya. Khusus untuk UUID, nilainya bukan didefinisikan oleh pengguna aplikasi, namun dibuat otomatis oleh sistem.

Ada banyak package untuk membuat UUID. Salah satu package untuk PHP yang paling sering digunakan adalah UUID Generator yang dikembangkan oleh Ben Ramsey. Instalasi dan penggunannya sangat gampang. Kita cukup menginstalnya menggunakan Composer, kemudian mengimpor package tersebut pada skrip yang ingin kita gunakan, kemudian generate UUID menggunakan method yang telah disediakan.

composer require ramsey/uuid
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;

try {
    echo $this->attributes['uuid'] = Uuid::uuid4()->toString();
} catch (UnsatisfiedDependencyException $e) {
    echo $e->getMessage();
}

Menggunakan potongan skrip di atas untuk meng-generate UUID setiap kali mau create data cukup melelahkan, apalagi kita menggunakan UUID pada hampir semua model/tabel dalam pangkalan data. Oleh karenanya, kita perlu otomatisasi agar UUID di-generate oleh skrip sama yang menghasilkan data berbeda.

Untuk membuat generator UUID secara otomatis, kita bisa menambahkan method boot() Eloquent dalam masing-masing model.

protected static function boot()
{
    parent::boot();
}

Sebagai contoh, saya mengimplementasikannya pada model App\User.php bawaan Laravel. Skrip lengkap dapat dilihat pada media di bawah.

<?php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;
use Ramsey\Uuid\Uuid;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'uuid',
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    protected static function boot()
    {
        parent::boot();

        static::creating(function ($model) {
            try {
                $model->uuid = Generator::uuid4()->toString();
            } catch (UnsatisfiedDependencyException $e) {
                abort(500, $e->getMessage());
            }
        });
    }
}

Perhatikan dari baris ke 39. Saya menggunakan static method pada event creating untuk mendefinisikan nilai awal sebuah UUID. Jika menggunakan nama kolom selain uuid, kalian bisa menggantinya sendiri pada bagian $model->uuid.

Sampai di sini, kita sudah berhasil membuat UUID yang secara otomatis yang di-generate oleh model. Untuk membuat data baru, tentunya kita tidak perlu lagi mendefinisikan nilai untuk atribut uuid. Sebagai contoh:

$user = User::create([
    'name' => $faker->name,
    'email' => $faker->email,
    'password' => bcrypt($faker->password),
]);

Lumayan mempersingkat baris bukan? Jika menggunakan method create() di banyak tempat, kalian akan merasakan efesiensinya generator UUID tersebut.

Tapi, tunggu dulu, bisa saja kita menggunakan generator UUID itu di banyak model bukan? Apakah kita harus menambahkan method boot() dalam setiap model yang menggunakan UUID?

Secara teknis iya, kita harus menambahkan method dalam setiap model yang menggunakan UUID. Beruntungnya bagi kalian yang suka copy-paste, hal tersebut tidak perlu dilakukan secara manual. Kita bisa memanfaatkan Trait dalam PHP yang diperkenalan dalam versi 5.4 untuk menyalin method tersebut dengan lebih efesien dan elegan. Bagaimana caranya?

Buat berkas baru dengan nama Uuid.php dalam direktori app/Traits (buat direktorinya jika belum ada). Tambahkan trait baru dengan nama Uuid dalam berkas tersebut. Jangan lupa memindahkan method boot() dalam model sebelumnya ke dalam trait Uuid. Tidak ada perubahan skrip sama sekali dalam method boot() dalam trait Uuid.

Jangan lupa untuk mengimpor package UUID. Oh ya, dalam skrip ini saya menggunakan nama Generator sebagai alias class Uuid untuk menghindari konflik dengan nama trait.

<?php

namespace App\Traits;

use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;
use Ramsey\Uuid\Uuid as Generator;

trait Uuid
{
    protected static function boot()
    {
        parent::boot();

        static::creating(function ($model) {
            try {
                $model->uuid = Generator::uuid4()->toString();
            } catch (UnsatisfiedDependencyException $e) {
                abort(500, $e->getMessage());
            }
        });
    }
}

Untuk menggunakannya, kita cukup mengimpor trait tersebut pada model yang mengimplentasikan UUID secara otomatis. Kemudian tambahkan katakunci use untuk menggunakan trait tersebut. Sebagai contoh implementasinya dalam model user.

<?php

namespace App;

use App\Traits\Uuid;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use Notifiable;
    use Uuid;
}

Lebih praktis bukan?

Tentunya, trait tersebut bisa kalian gunakan pada model sebanyak yang diinginkan tanpa perlu copy-paste skripnya secara manual. Codebase jauh lebih rapi dan efesien.

Tak Berkategori

Yugo Purwanto

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

3 comments

Tinggalkan Balasan