Using the `InteractsWithUuid` Trait to Manage UUIDs in Laravel
Nasrul Hazim Bin Mohamad
Posted on September 12, 2024
In modern web applications, using UUIDs (Universally Unique Identifiers) as primary keys offers several advantages over traditional auto-incrementing integers, such as better security, easier data replication, and ensuring uniqueness across distributed databases. Laravel makes it easy to work with UUIDs, and using traits can make the implementation even more straightforward.
In this blog post, we'll dive into a custom InteractsWithUuid
trait that simplifies the use of UUIDs in Laravel models, how to set it up, and how to customize it for your specific needs.
The InteractsWithUuid
Trait Explained
The InteractsWithUuid
trait provides functionality for automatically generating UUIDs for your models, using UUIDs as route keys, and adding query scopes for searching by UUID. Here is the code for the trait:
namespace App\Concerns;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
trait InteractsWithUuid
{
public static function bootInteractsWithUuid()
{
static::creating(function (Model $model) {
if (Schema::hasColumn($model->getTable(), $model->getUuidColumnName()) && is_null($model->{$model->getUuidColumnName()})) {
$model->{$model->getUuidColumnName()} = Str::orderedUuid();
}
});
}
/**
* Get the route key for the model.
*/
public function getRouteKeyName(): string
{
return $this->getUuidColumnName();
}
/**
* Get UUID Column Name.
*/
public function getUuidColumnName(): string
{
return isset($this->uuid_column) ? $this->uuid_column : 'uuid';
}
/**
* Scope a query to include only by UUID.
*/
public function scopeUuid(Builder $query, $value): Builder
{
return $query->where($this->getUuidColumnName(), $value);
}
}
Key Features of the InteractsWithUuid
Trait
-
Automatic UUID Generation:
- The
bootInteractsWithUuid
method listens to thecreating
event of the model and automatically assigns a UUID to the model if it is not already set. It usesStr::orderedUuid()
to generate the UUID, which is a time-ordered UUID string, providing better performance for indexing in databases.
- The
-
Custom Route Key:
- By overriding the
getRouteKeyName
method, the trait ensures that the UUID column is used as the route key, allowing you to use UUIDs in route model binding seamlessly.
- By overriding the
-
Customizable UUID Column:
- The
getUuidColumnName
method allows for a customizable UUID column name. By default, it looks for a column nameduuid
, but you can override this by defining a$uuid_column
property in your model.
- The
-
Query Scope for UUID:
- The
scopeUuid
method allows you to query models by UUID, providing a convenient way to filter records.
- The
How to Use the InteractsWithUuid
Trait in Your Models
To use the InteractsWithUuid
trait, you simply need to import it into your model:
namespace App\Models;
use App\Concerns\InteractsWithUuid;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use InteractsWithUuid;
// Optionally, specify a custom UUID column name
protected $uuid_column = 'custom_uuid';
}
Example Migration for UUID with Index
To use the InteractsWithUuid
trait effectively, you need to add a UUID column to your database table. Here’s an example migration for a posts
table that includes a UUID column with an index:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePostsTable extends Migration
{
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->uuid('uuid')->unique(); // Add a UUID column with a unique index
$table->string('title');
$table->text('content');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('posts');
}
}
Customizing the UUID Field
If you need to customize the UUID column, you can easily do so by modifying the $uuid_column
property in your model. For example, if you want to use a column named custom_uuid
instead of the default uuid
:
namespace App\Models;
use App\Concerns\InteractsWithUuid;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use InteractsWithUuid;
// Specify the custom UUID column name
protected $uuid_column = 'custom_uuid';
}
And then adjust your migration accordingly:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePostsTable extends Migration
{
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->uuid('custom_uuid')->unique(); // Custom UUID column name
$table->string('title');
$table->text('content');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('posts');
}
}
Conclusion
The InteractsWithUuid
trait is a powerful and flexible way to manage UUIDs in your Laravel applications. By providing automatic UUID generation, customizable UUID columns, and query scopes, it simplifies the process of using UUIDs as primary keys or route keys. With the examples provided, you can easily integrate this trait into your Laravel models and customize it to fit your specific needs.
Posted on September 12, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.