Laravel 10 Use UUIDs in Laravel Models

Hello Artisan, today I'll show you how to Using UUIDs in Laravel Models.In this guide, we'll explore using UUIDs instead of auto-incrementing IDs in Laravel Eloquent models. But before we get started, let's grasp what UUIDs are, how they're created, and why they matter for your application.

Table of Contents

  1. What are UUIDs?
  2. Creating Laravel Application
  3. Creating UUID Trait
  4. Updating Migration File
  5. Using Trait in Our Model Class
  6. Testing using Laravel Seed Class
  7. Using UUIDs as Foreign Key

What are UUIDs?

In Laravel, UUIDs (Universally Unique Identifiers) are unique strings that are used as identifiers for records in a database. These UUIDs are generated in a way that ensures their uniqueness across different systems and databases, making them suitable for distributed and decentralized applications. Instead of using traditional auto-incrementing numeric IDs for database records, UUIDs provide a way to guarantee uniqueness without relying on a centralized database for ID generation. This can be especially valuable in scenarios where data needs to be synchronized across multiple databases or systems.

Creating Laravel Application

For the purpose of this tutorial, we will be using Laravel 8 but this can work on any older version of Laravel.

Let’s start by creating a new Laravel application using composer.

composer create-project laravel/laravel laravel-uuids-example

To create a Laravel application using the latest stable release, you'll need to incorporate the Ramsey UUID library, which facilitates the generation of universally unique identifiers (UUIDs).

Starting from Laravel 5.6, the Ramsey UUID package is included in the Laravel application by default, eliminating the need for a separate installation. To transition our models from auto-incrementing IDs to UUIDs, we'll need to modify our model classes. To maintain clean code and reusability, we'll employ a PHP Trait to handle these changes. This Trait can also be applied to other models in the future if necessary.

Creating UUID Trait

Create a new folder inside app folder and name it Traits. Now add a new PHP file in this folder named Uuids.php. Now add below code in this newly created file.

<?php

namespace App\Traits;

use Illuminate\Support\Str;

trait Uuids
{
   /**
     * Boot function from Laravel.
     */
    protected static function boot()
    {
        parent::boot();
        static::creating(function ($model) {
            if (empty($model->{$model->getKeyName()})) {
                $model->{$model->getKeyName()} = Str::uuid()->toString();
            }
        });
    }

   /**
     * Get the value indicating whether the IDs are incrementing.
     *
     * @return bool
     */
    public function getIncrementing()
    {
        return false;
    }

   /**
     * Get the auto-incrementing key type.
     *
     * @return string
     */
    public function getKeyType()
    {
        return 'string';
    }
}

In the code snippet, Eloquent assumes the primary key is a regular incrementing integer. To switch to using UUID as the primary key, we make two changes:

Set the primary key type to a string by using $keyType = 'string'.

Disable the incrementing behavior by setting $incrementing = false.

To generate and convert the UUID to a string, we override the boot method of the model and use the Illuminate\Support\Str facade.

Updating Migration File

Next, a very important step is to update our migration file, I want to use the UUIDs in my User class so I will make changes to my User’s migration class.

In your migration file, change below:

$table->id();

to this:

$table->uuid('id')->primary();

please make the necessary changes to your .env file by providing the correct database name, username, and password. Afterward, execute the following command to perform table migration to the database.

php artisan migrate

Using Trait in Our Model Class

Next, we need to add the Uuid.php trait to our User model. Simply add the trait like below.

<?php

namespace App\Models;

use App\Traits\Uuids;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
	use Uuids;
    use HasFactory, Notifiable;

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

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

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}

Testing using Laravel Seed Class

Now that everything is set up, let's test the model class. Laravel includes a UserFactory class by default, which can be found in the database/factories directory.

If you open the DatabaseSeeder class located in the database/seeders folder, you'll notice that the call to the User factory is currently commented out. Simply uncomment this line, and your DatabaseSeeder class will look like this:

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        \App\Models\User::factory(10)->create();
    }
}

Now let’s run the seeder. In your terminal, type:

php artisan db:seed

That’s it. Now let’s check the Users table to see the data generated. You will find out the id column uses UUID and not the incremented id.

Using UUIDs as Foreign Key

If you want to use a UUID primary key as a foreign key in another table, you'll need to update the column type to UUID in the table where the foreign key is defined. For instance, if every user has a profile, you'll need to change the data type of the user_id column in the profiles table from its current type to UUID.

$table->bigInteger('user_id')->unsigned();

to below:

$table->uuid('user_id');

UUIDs in Laravel can protect the security of your record IDs by concealing them, but they may have performance implications in large databases with limited computing resources. That’s all for now, I hope you will find this post useful.