Como gerar UUIDs automaticamente para seus models do Laravel — Parte I
TL;DR
Desenvolvi um pacote simples, flexível, de fácil customização e 100% coberto por testes automatizados que facilita a geração de UUIDs automaticamente nos models Eloquent do Laravel.
Introdução
Um UUID é um identificador universalmente exclusivo utilizado para identificação de qualquer coisa no mundo da computação.
Eu escrevi um artigo bem detalhado sobre o que é UUID? Porque usá-lo? Se você ainda não conhece, ou não leu esse artigo, recomendo fortemente que faço isso agora.
Um pouco de história…
No PHP existe uma excelente biblioteca para lidar com a geração de UUIDs: https://github.com/ramsey/uuid .
Para gerar um UUID na versão 4, basta isso:
Uuid::uuid4();
O que pouca gente sabe é que essa biblioteca está incluída nas dependências do Laravel Framework desde a sua versão 5.3 . Ou seja, quando você instala o Laravel 5.3 ou superior, automaticamente a biblioteca Ramsey/Uuid já está disponível na pasta Vendor da aplicação e você pode utiliza-la em qualquer lugar do seu projeto.
A versão 5.6 do Laravel introduziu novos métodos pra geração de UUID na classe Illuminate/Support/Str.php, esses métodos utilizam a biblioteca Ramsey/Uuid. Isso acabou popularizando um pouco mais o UUID no ecossistema Laravel.
Agora, prometo que vou parar de enrolação e vou direto ao assunto desse artigo.
Gerando UUIDs automaticamente — Eloquent Laravel
Isso é algo relativamente simples de se fazer, basta “escutar” o evento creating — do Eloquent — passando pra ele uma função anônima com a lógica responsável pela geração do UUID. Uma maneira eficiente de se fazer isso é criar uma Trait contendo essa lógica, veja:
<?phpnamespace App\Traits;use Ramsey\Uuid\Uuid;trait Uuid
{
public static function bootUuid()
{
static::creating(function ($model) {
$model->uuid = Uuid::uuid4();
});
}
}
Agora basta utilizar essa Trait no seu model e pronto! O model em questão irá receber um UUID — gerado pela classe Ramsey\Uuid — automaticamente no momento em que um novo registro for inserido na base de dados.
<?php// app\User.phpuse App\Traits\Uuid;
use Illuminate\Database\Eloquent\Model;class User extends Model
{
use Uuid;
// ...
}// ATENÇÃO: Esse código é apenas pra ilustrar o uso da Trait Uuid em um model Eloquent qualquer... Não use esse exemplo na sua aplicação!
Nota: Se você não conhece a maneira como o model carrega esse tipo de Trait no Eloquent, recomendo a leitura desse artigo: Laravel além do básico: #1 — Bootable traits no Eloquent.
Dando continuidade, essa abordagem é uma das mais simples possível! Agora convenhamos, nos tempos atuais desenvolver o mínimo não basta… Por ser bastante simples, esse exemplo de Trait acaba sendo bastante limitado e engessado.
Não reinvente a roda — Usando Pacotes!
Claro que já existem diversos pacotes do Laravel que abstraem toda essa lógica, o que acaba facilitando e muito nosso trabalho. Porém, ao testar alguns dos pacotes mais populares notei vários pontos que estavam me incomodando e que mereciam um pouco de atenção. Seguem abaixo:
- Não possuíam testes automatizados… Como eu posso confiar em uma dependência de terceiro que não possui testes? E se o mantenedor mexer em algo e lançar uma release com bug… Pra evitar constrangimentos eu prefiro não depender de algo que não possui testes, simples assim!
- Assumiam que a coluna que representa o ‘uuid’ na base de dados, sempre teria esse nome de ‘uuid’. Mas, o banco de dados é meu, e se eu quiser colocar outro nome como por exemplo ‘universally_unique_id’ ou simplismente ‘id’? Problema detectado!
- Não forneciam uma proteção caso o usuário tenta-se alterar o uuid na atualização dos dados. (usuários nunca devem ser capazes de gerar seus próprios UUIDs nem podem substituí-los). Problema detectado!
- Não permitiam trocar a versão do UUID gerado. Exemplo: O pacote gerava UUID na versão 4. Mas, se eu quiser gerar um UUID na versão 3 ou qualquer outra versão? Problema detectado!
- Assumiam que o ‘uuid’ seria sempre a chave primária da tabela. Mas, se eu quiser manter as chaves primarias ID auto-increment pra uso interno e usar os UUIDs como referência nas URLs? Problema detectado!
- Não forneciam uma maneira fácil de serem customizados ou ‘extensíveis’. (Não chega a ser um problema, mas seria uma comodidade.)
- Não forneciam uma scope query para facilitar a busca no model através de UUID. (Não chega a ser um problema, mas seria uma comodidade.)
- Não forneciam suporte para utilizar implicit model binding. (Não chega a ser um problema, mas seria uma comodidade.)
Obviamente que os pontos citados acima foram encontrados de forma aleatória nos pacotes que eu testei. Juntando tudo isso veio a motivação para criar um pacote que “resolveria” tudo que estava me incomodando. Foi assim que nasceu o your-app-rocks/eloquent-uuid .
Por hoje é só! na parte 2 desse artigo eu explico detalhadamente como utilizar o pacote.
̶C̶o̶m̶o̶ ̶g̶e̶r̶a̶r̶ ̶U̶U̶I̶D̶s̶ ̶a̶u̶t̶o̶m̶a̶t̶i̶c̶a̶m̶e̶n̶t̶e̶ ̶p̶a̶r̶a̶ ̶s̶e̶u̶s̶ ̶m̶o̶d̶e̶l̶s̶ ̶d̶o̶ ̶L̶a̶r̶a̶v̶e̶l̶ ̶ — ̶ ̶P̶a̶r̶t̶e̶ ̶2̶ (Ainda trabalhando nisso! Aguarde…)
Gosta de Laravel? Dá uma olhadinha nisso:
5 lições que aprendi durante 4 anos utilizando o Laravel Framework
Laravel além do básico: #0 — Introdução
Leia mais dos meus artigos em: