Programster's Blog

Tutorials focusing on Linux, programming, and open-source

Laravel - Use UUID For Model ID

The default Laravel setup is for you to be using auto-incrementing integer IDs against a MySQL setup. I prefer to use PostgreSQL with UUIDs for the primary key. This tutorial will show you how you can quickly add a UUID trait, which you can then add to your models, so that they are using a UUID for their primary key/identifier.

Steps

Create a folder inside app called Traits if you haven't already. We will store all traits in here.

mkdir app/Traits

Now we need to create a trait which we will give to your models, in order to "convert" them to being UUID-based for their IDs, rather than an auto incrementing number.

editor app/Traits/TraitUuid

I am using the Trait prefix on the class name because I find this useful when finding files by name in my IDE. I do the same with interfaces and abstract classes.

<?php

namespace App\Traits;

use Illuminate\Support\Str;


trait TraitUuid
{
    /**
     * Override the boot function from Laravel so that 
     * we give the model a new UUID when we create it.
     */
    protected static function boot()
    {
        parent::boot();

        $creationCallback = function ($model) {
            if (empty($model->{$model->getKeyName()}))
            {
                $model->{$model->getKeyName()} = Str::uuid()->toString();
            }
        };

        static::creating($creationCallback);
    }


    /**
     * Override the getIncrementing() function to return false to tell
     * Laravel that the identifier does not auto increment (it's a string).
     *
     * @return bool
     */
    public function getIncrementing() : bool
    {
        return false;
    }


    /**
     * Tell laravel that the key type is a string, not an integer.
     *
     * @return string
     */
    public function getKeyType() : string
    {
        return 'string';
    }
}

Now, to make a model UUID-based, simply add the trait to the model with: use TraitUuid; like so:

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens;
    use HasFactory;
    use Notifiable;
    use \App\Traits\TraitUuid;

Updating Migrations

Please note that if you apply the UUID change to the existing User model, then you will need to update your migrations. You should have one called create_users_table.php with the following code:

Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('email')->unique();
    $table->timestamp('email_verified_at')->nullable();
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});

Change this to:

Schema::create('users', function (Blueprint $table) {
    $table->uuid('id')->primary();
    $table->string('name');
    $table->string('email')->unique();
    $table->timestamp('email_verified_at')->nullable();
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});

MariaDB / MySQL Users

If you are using MySQL/MariaDB instead, then you may need to do the following instead:

Schema::create('users', function (Blueprint $table) {
    $table->string('uuid')->primary();
    $table->string('name');
    $table->string('email')->unique();
    $table->timestamp('email_verified_at')->nullable();
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});

Stub Customization

To prevent having to add the uuid trait manually to each model whenever you create a new model through artisan, you may wish to customize the stub so that it will automatically be there in future.

References

Last updated: 26th July 2022
First published: 17th September 2021

This blog is created by Stuart Page

I'm a freelance web developer and technology consultant based in Surrey, UK, with over 10 years experience in web development, DevOps, Linux Administration, and IT solutions.

Need support with your infrastructure or web services?

Get in touch