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
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
First published: 17th September 2021