Using UUIDs in Laravel Models
In this post, we will look at how we can use UUIDs in Laravel Eloquent models instead of incrementing Ids. Before diving into this tutorial, we need to understand what UUIDs are, how they are formed, and what are the implications of using them in your application.
What are UUIDs?
UUIDs stands for Universally Unique Identifiers and are 128 bits values used to uniquely identify some record in our database. UUIDs are represented as a hexadecimal string split into five groups separated by hyphens.
There is a big debate on the advantages and disadvantages of using UUIDs in your database, here are some of the disadvantages of using UUIDs over the top of my head.
- UUIDs are based on 16 bit instead of an integer’s 4 bit or big integer’s 8 bit. So It will take more space for storage and indexing.
- Because the size of UUIDs are big, so it will occupy more RAM to cache them in memory.
- UUIDs are not generated sequentially like integer primary keys the index will be messier and tend to suffer from more bloat.
- Sorting can be done easily with the integer incrementing value, UUIDs won’t sort in a logical order as they are generated at random.
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
This will create a Laravel application with the latest stable release version. To use UUIDs in Laravel we have to use Ramsey UUID library, which helps to generate universally unique identifiers.
Since, Laravel 5.6, the Ramsey UUID package is part of the Laravel application, so you don’t have to install it separately.
To change our models to use UUIDs instead of incrementing Ids, we have to make some changes to our model class, I like to keep things clean so will be using the PHP Trait for these changes. Later on, we can use the same trait in other models if we want to.
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'; } }
Let’s go through the above code snippet. By default, Eloquent assumes that the primary key on a model is incrementing integer value. To use UUID, we need to specify that the primary key is a string value and not an incrementing value. We achieve this by setting the $keyType to string and $incrementing to false.
We also override the boot method of the model to use UUID. We use the Illuminate\Support\Str facade to generate the UUID and then convert it to string value.
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();
Now, update your .env
file with the right database name, username, and password, and then run the below command to migrate all tables 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 (in my case). 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 everything is setup, we will test the model class. By default Laravel comes with a UserFactory class located in database/factories
.
If you open the DatabaseSeeder class located in database/seeders
folder, you will find out the call to User’s factory which is commented out. Un-comment this line and you will have DatabaseSeeder class like below.
<?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 are using a UUID primary key as a foreign key in another table, you need to change the column type to UUID, where the foreign key is defined.
For example, let’s assume every user has a profile. Your user_id column in the profiles table will need to change from
$table->bigInteger('user_id')->unsigned();
to below:
$table->uuid('user_id');
Final Words
UUIDs in Laravel application can be useful when you don’t want to expose the ids of your records for security reasons, while there are implications of using them when you have a big database and fewer computing resources.
That’s all for now, I hope you will find this post useful. If you have any suggestions to improve this post, please let us know in the comment box below.