Menggunakan UUID Sebagai Primary Key Di Laravel

By Rizky Kurniawan - September 27, 2022 ~6 mins read

Halo Talenta Digital! Gimana kabarnya hari ini? Semoga tetap semangat buat belajar ya…

Selamat datang kembali di blog Ruang Developer. Pada kesempatan kali ini, kita akan belajar framework laravel ya. Kita akan belajar bagaimana cara menggunakan UUID sebagai primary key di laravel.

Kalau kamu belum tau apa itu framework laravel, kamu bisa baca dulu postingan kita sebelumnya tentang framework laravel di sini.

Primary Key Di Laravel

Kalau kamu pernah mencoba laravel, kemungkinan besar kamu akan menyadari bahwa secara default laravel akan membuatkan primary key bertipe integer dan auto increment ketika kita membuat database migration untuk membuat tabel. Kamu juga bisa melihat pada file migrasi bawaan laravel untuk tabel users yang juga menggunakan primary key bertipe integer dan auto increment secara default.

Update: Laravel versi 9 telah memiliki fitur UUID untuk primary key yang dapat diterapkan dengan mudah dan singkat, selengkapnya bisa kamu cek di dokumentasi resminya: https://laravel.com/docs/9.x/eloquent#uuid-and-ulid-keys

Apa Yang Salah Dengan Auto Increment?

Sebenarnya tidak ada yang salah ya jika menggunakan auto increment untuk membuat primary key. Namun, jika aplikasi yang kamu buat memiliki skala yang besar mungkin kamu bisa mempertimbangkan kembali jika ingin menggunakan auto increment.

Auto incrmeent mungkin akan menimbulkan beberapa masalah dalam hal database replica dan database sharding. Berikut ini beberapa referensi yang bisa kamu baca mengenai database replica dan database sharding.

Data Replication in DBMS

Understanding Database Sharding

Selain itu, auto increment mungkin akan mudah ditebak jika ditampilkan pada url contohnya seperti berikut:

https://example.com/users/39

Dibandingkan dengan ini:

https://example.com/users/028d9b18-c274-4f7c-bb70-9e7020a9ce9f

Di samping itu, jika tabel yang kamu buat hanya menyimpan data statis yang simpel contohnya seperti jenis user atau kategori buku, penggunaan autoincrement sepertinya tidak begitu bermasalah.

Menggunakan UUID Primary Key Di Laravel

Sebagai bahan percobaan, kamu bisa siapkan dulu project laravel baru dan buat database untuk project kamu. Jangan lupa untuk konfigurasi koneksi database di environment variable ya.

Setelah membuat project dan konfigurasi database, langkah selanjutnya kita akan membuat contoh data sederhana yaitu student.

Buka terminal kamu dan jalankan perintah berikut untuk membuat model student beserta migrasinya.

php artisan make:model Student -m

Setelah itu, edit skema untuk table students pada file migrasi student menjadi seperti ini:

Schema::create('students', function (Blueprint $table) {
  $table->uuid('id')->primary(); // menggunakan uuid sebagai primary key
  $table->string('name');
  $table->string('class');
  $table->timestamps();
});

Jangan lupa simpan perubahannya. Setelah itu, kita bisa lakukan migrasi database.

Sekarang tabel students sudah dibuat dan menggunakan uuid sebagai primary key. Namun, saat ini jika kita ingin membuat data student baru kita harus membuat UUID secara manual. Tentu ini bisa sangat merepotkan ya. Oleh karena itu kita akan memodifikasi model Student kita agar menjadi seperti berikut ini:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

class Student extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
        'class'
    ];

    /**
     * Kita override boot method
     *
     * Mengisi primary key secara otomatis dengan UUID ketika membuat record
     */
    protected static function boot()
    {
        parent::boot();
        static::creating(function ($model) {
            if (empty($model->{$model->getKeyName()})) {
                $model->{$model->getKeyName()} = Str::uuid()->toString();
            }
        });
    }

    /**
     * Kita override getIncrementing method
     *
     * Menonaktifkan auto increment
     */
    public function getIncrementing()
    {
        return false;
    }

    /**
     * Kita override getKeyType method
     *
     * Memberi tahu laravel bahwa model ini menggunakan primary key bertipe string
     */
    public function getKeyType()
    {
        return 'string';
    }
}

Sekarang ketika kita membuat data student baru kita tidak perlu membuat UUID secara manual karena telah dibuat otomatis.

Kita bisa mencoba menambahkan data student menggunakan bantuan tinker.

php artisan tinker

Data masih kosong:

>>> Student::all()
=> Illuminate\Database\Eloquent\Collection {#3964
     all: [],
   }

>>>

Coba membuat data:

>>> Student::create(['name' => 'Rizky Kurniawan', 'class'=> 'XII C'])
=> App\Models\Student {#4368
     name: "Rizky Kurniawan",
     class: "XII C",
     id: "3be14193-bce3-468f-abd6-1b5ad5ffd716",
     updated_at: "2022-09-27 03:11:16",
     created_at: "2022-09-27 03:11:16",
   }

>>>

Membuat data lagi:

>>> Student::create(['name' => 'Ruang Developer', 'class'=> 'XII A'])
=> App\Models\Student {#3964
     name: "Ruang Developer",
     class: "XII A",
     id: "18b1a264-a5ae-4422-9b61-07994d988959",
     updated_at: "2022-09-27 03:12:35",
     created_at: "2022-09-27 03:12:35",
   }

>>>

List data:

>>> Student::all()
=> Illuminate\Database\Eloquent\Collection {#4606
     all: [
       App\Models\Student {#4604
         id: "3be14193-bce3-468f-abd6-1b5ad5ffd716",
         name: "Rizky Kurniawan",
         class: "XII C",
         created_at: "2022-09-27 03:11:16",
         updated_at: "2022-09-27 03:11:16",
       },
       App\Models\Student {#4580
         id: "18b1a264-a5ae-4422-9b61-07994d988959",
         name: "Ruang Developer",
         class: "XII A",
         created_at: "2022-09-27 03:12:35",
         updated_at: "2022-09-27 03:12:35",
       },
     ],
   }

>>>

Nah, sekarang kamu bisa melihat bahwa UUID untuk primary key kita secara otomatis dibuatkan ketika membuat data baru.

NB: Di sini saya menggunakan laravel versi 9.*

UUID Sebagai Foreign Key

Ketika kita ingin mendefinisikan foreign key yang bertipe UUID, kita bisa menggunakan method berikut ini:

$table->foreignUlid('nama kolom');

Sebagai contoh, dengan cara yang sama seperti sebelumnya saya membuat tabel dan model baru untuk menyimpan score. Berikut skema tabelnya:

Schema::create('scores', function (Blueprint $table) {
  $table->uuid('id')->primary();
  $table->foreignUlid('student_id'); // foreign id untuk tabel student
  $table->integer('score');
  $table->timestamps();
});

Dan ini adalah Score model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

class Score extends Model
{
    use HasFactory;

    protected $fillable = [
        'student_id',
        'score',
    ];

    public function student()
    {
        return $this->belongsTo(Student::class);
    }

    /**
     * Kita override boot method
     *
     * Mengisi primary key secara otomatis dengan UUID ketika membuat record
     */
    protected static function boot()
    {
        parent::boot();
        static::creating(function ($model) {
            if (empty($model->{$model->getKeyName()})) {
                $model->{$model->getKeyName()} = Str::uuid()->toString();
            }
        });
    }

    /**
     * Kita override getIncrementing method
     *
     * Menonaktifkan auto increment
     */
    public function getIncrementing()
    {
        return false;
    }

    /**
     * Kita override getKeyType method
     *
     * Memberi tahu laravel bahwa model ini menggunakan primary key bertipe string
     */
    public function getKeyType()
    {
        return 'string';
    }
}

Jangan lupa tambahkan relasi juga di Student model:

public function score()
{
  return $this->hasOne(Score::class);
}

Coba nambah score melalui tinker:

>>> Score::create(['student_id' => '3be14193-bce3-468f-abd6-1b5ad5ffd716', 'score' => 90])
=> App\Models\Score {#4613
     student_id: "3be14193-bce3-468f-abd6-1b5ad5ffd716",
     score: 90,
     id: "290249eb-b1e7-4496-a47d-c190fe06add2",
     updated_at: "2022-09-27 03:35:32",
     created_at: "2022-09-27 03:35:32",
   }

>>>

List data score:

>>> Score::with('student')->get()
=> Illuminate\Database\Eloquent\Collection {#3623
     all: [
       App\Models\Score {#4616
         id: "290249eb-b1e7-4496-a47d-c190fe06add2",
         student_id: "3be14193-bce3-468f-abd6-1b5ad5ffd716",
         score: 90,
         created_at: "2022-09-27 03:35:32",
         updated_at: "2022-09-27 03:35:32",
         student: App\Models\Student {#4621
           id: "3be14193-bce3-468f-abd6-1b5ad5ffd716",
           name: "Rizky Kurniawan",
           class: "XII C",
           created_at: "2022-09-27 03:11:16",
           updated_at: "2022-09-27 03:11:16",
         },
       },
     ],
   }

>>>

Menggunakan Trait Pada Model Untuk Membuat UUID

Sekarang jika kamu perhatikan, kita menuliskan kode yang sama pada Student model dan Score model untuk membuat UUID. Hal ini tentu sangat tidak efisien dalam penulisan kode. Oleh karena itu, kita bisa memisahkan bagian pembuatan uuid ke menjadi sebuah trait sehingga bisa kita panggil pada setiap model yang membutuhkan uuid sebagai primary key.

Dalam folder app buatlah folder baru bernama Traits, dan di dalamnya buat satu buah file bernama UUIDAsPrimaryKey.php yang berisi kode trait seperti berikut:

<?php

namespace App\Traits;

use Illuminate\Support\Str;

trait UUIDAsPrimaryKey
{
    /**
     * Kita override boot method
     *
     * Mengisi primary key secara otomatis dengan UUID ketika membuat record
     */
    protected static function boot()
    {
        parent::boot();
        static::creating(function ($model) {
            if (empty($model->{$model->getKeyName()})) {
                $model->{$model->getKeyName()} = Str::uuid()->toString();
            }
        });
    }

    /**
     * Kita override getIncrementing method
     *
     * Menonaktifkan auto increment
     */
    public function getIncrementing()
    {
        return false;
    }

    /**
     * Kita override getKeyType method
     *
     * Memberi tahu laravel bahwa model ini menggunakan primary key bertipe string
     */
    public function getKeyType()
    {
        return 'string';
    }
}

Sekarang kita bisa menggunakan trait tersebut di semua model yang membutuhkan UIID sebagai primary key.

Mari kita ubah Student model menggunakan trait UUIDAsPrimaryKey agar lebih ringkas menjadi seperti ini:

<?php

namespace App\Models;

use App\Traits\UUIDAsPrimaryKey;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Student extends Model
{
    use HasFactory, UUIDAsPrimaryKey;

    protected $fillable = [
        'name',
        'class'
    ];

    public function score()
    {
        return $this->hasOne(Score::class);
    }
}

Score model juga:

<?php

namespace App\Models;

use App\Traits\UUIDAsPrimaryKey;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Score extends Model
{
    use HasFactory, UUIDAsPrimaryKey;

    protected $fillable = [
        'student_id',
        'score',
    ];

    public function student()
    {
        return $this->belongsTo(Student::class);
    }
}

Kesimpulan

Selamat! Sekarang kamu sudah bisa menggunakan UUID sebagai alternatif primary key selain integer auto increment. Selain UUID, masih ada beberapa alternatif yang bisa kamu gunakan untuk membuat primary key. Salah satunya adalah fungsi uniqid() milik php.

Bagikan:

Ingin Berdiskusi?

Yuk bergabung di Grup Telegram Ruang Developer atau mulai diskusi melalui GitHub. See You!

Dapatkan contoh source code project backend, frontend, atau fullstack untuk kamu amati, tiru, dan modifikasi sesuka hati. Klik untuk melihat detail!
comments powered by Disqus

Berlangganan Gratis

Kamu akan menerima email update dari Ruang Developer

Beri Dukungan

Beri dukungan, dapatkan full source code project web untuk bahan referensi, tiru, dan modifikasi.
Lightbox