PauloRB.dev

Desenvolvedor de Software

Por que whereNull não funciona com updateOrCreate no Laravel (e como evitar bugs silenciosos) | PauloRB.dev Por que whereNull não funciona com updateOrCreate no Laravel (e como evitar bugs silenciosos) – PauloRB.dev
Por que whereNull não funciona com updateOrCreate no Laravel (e como evitar bugs silenciosos)

Por que whereNull não funciona com updateOrCreate no Laravel (e como evitar bugs silenciosos)

O updateOrCreate() é um dos métodos mais utilizados no Eloquent para garantir que registros sejam atualizados ou criados sem duplicações. Porém, muitos desenvolvedores (inclusive os mais experientes) acabam caindo numa armadilha silenciosa: o uso de campos NULL — especialmente o deleted_at — na cláusula de condição.

Se você já escreveu algo assim:

Model::updateOrCreate([
    'user_id' => $id,
    'deleted_at' => null,
], [...]);

⚠️ Pare agora. Isso não funciona como você pensa.

🔍 O problema

O updateOrCreate() do Eloquent traduz internamente o array de condições em comparações simples =. Então quando você faz 'deleted_at' => null, o Laravel não gera um WHERE deleted_at IS NULL, e sim:

O problema? Em SQL, = NULL nunca é verdadeiro. O resultado é que:

  • Nenhum registro é encontrado,

  • Eloquent presume que precisa criar um novo,

  • E você acaba com registros duplicados, mesmo que pareça que está fazendo tudo certo.

✅ A solução correta

$registro = Model::where('user_id', $id)
    ->whereNull('deleted_at')
    ->first();

if (!$registro) {
    $registro = new Model();
    $registro->user_id = $id;
}

$registro->campo1 = 'valor';
$registro->campo2 = 'valor';
$registro->save();

Agora sim, a consulta IS NULL funciona corretamente, e você evita duplicações silenciosas.

💡 Dica extra: proteja no banco

Mesmo com a lógica certa no código, ainda é possível cometer erros. Garanta unicidade no banco com índices condicionais:

CREATE UNIQUE INDEX idx_user_unico
ON minha_tabela (user_id)
WHERE deleted_at IS NULL;

O método updateOrCreate é poderoso, mas não foi feito para lidar com NULL em comparações de forma transparente. Use whereNull() quando necessário e, se possível, complemente com um índice único no banco de dados.

 

Mais Posts

Como Configurar e Gerenciar um Banco de Dados MySQL com Docker Compose

Como Configurar e Gerenciar um Banco de Dados MySQL com Docker Compose

Configurar e gerenciar bancos de dados pode ser uma tarefa desafiadora, especialmente quando você precisa garantir a portabilidade e a... Leia mais

Como resolver o erro “oauth-private.key does not exist or is not readable” no Laravel

Como resolver o erro “oauth-private.key does not exist or is not readable” no Laravel

O Laravel Passport é uma biblioteca que trabalha com o padrão OAuth2 e fornece uma implementação completa do servidor OAuth2.... Leia mais

Entendendo as Diferenças Entre Programação Orientada a Objetos e Funcional: Java vs. Elixir

Entendendo as Diferenças Entre Programação Orientada a Objetos e Funcional: Java vs. Elixir

A escolha entre programação orientada a objetos (OOP) e programação funcional (FP) é mais do que uma preferência de estilo;... Leia mais

Converter campos de um banco de dados do tipo json para array com laravel

Converter campos de um banco de dados do tipo json para array com laravel

Hoje boa parte dos banco de dados relacionais podem armazenar campos com valores no formato JSON o que garante maior... Leia mais