UUID como primary key em Laravel
Uma das coisas que normalmente temos problemas quando uma api é consumida por muitos lados ou quando é preciso garantir que dados não sejam reescritos de diversas formas ou quando precisamos trabalhar com “offline-first” apps é garantir que as primary keys não sejam duplicadas.
Tem várias formas de fazer isso, garantindo que os mesmo dados não estão já lá no banco de dados antes de inseri-los novamente, ter ids separadas em cada aplicação sem distinção, usar bancos diferentes para diversos clientes, etc.
Mas uma delas, que é muito boa, é fazer o uso de unique identifiers. E usando o Laravel, isso se torna ainda mais fácil!
Para começar, crie uma Trait em um lugar oportuno (por exemplo, dentro de app/Models/Traits
. No nosso caso vamos chama-la de HasUuid
.
Após isso adicione o seguinte código dentro dela.
<?php
namespace App\Models\Traits;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
trait HasUuid
{
public function getIncrementing()
{
return false;
}
public function getKeyType()
{
return 'string';
}
protected static function boot()
{
parent::boot();
static::creating(
function (Model $model) {
if (!$model->getKey()) {
$model->setAttribute($model->getKeyName(), Str::uuid()->toString());
}
}
);
static::saving(
function ($model) {
$primaryKey = $model->getOriginal('id');
if ($primaryKey !== $model->id) {
$model->id = $primaryKey;
}
}
);
}
}
Agora, vamos criar um novo Model para usar nossa Trait.
php artisan make:model Product -m
o -m
é para criarmos também uma migration para a tabela no banco de dados. Na migration vamos apenas criar um campo para o nome do produto e alterar o tipo da primary key.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('products', function (Blueprint $table) {
// $table->id();
$table->uuid('id')->primary();
$table->string('name', 200);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('products');
}
};
Agora, tudo que precisamos fazer é alterar nosso model para usar a Trait que criamos. Lembre de rodar php artisan migrate
!
<?php
namespace App\Models;
use App\Models\Traits\HasUuid;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
use HasFactory, HasUuid; // <-- adicione a Trait!
}
Agora, se você criar um novo produto usando a model que criamos vai ter um resultado parecido com o debaixo:
array:4 [▼ // routes/web.php:24
"name" => "Product Amazing!"
"id" => "4e9aa680-00f7-4408-aadb-71a94b047097"
"updated_at" => "2022-11-02T10:06:07.000000Z"
"created_at" => "2022-11-02T10:06:07.000000Z"
]
E é isso gente! Espero que isso tenha ajudado de alguma forma! Se desejar, pode fazer o download direto do meu gist no github. Sucesso sempre e good coding! 😉