Desafio PHP
Trait com método abstrato e validação
Enunciado
Crie uma trait Validavel com um método abstrato regras(): array e um método concreto validar(array $dados): bool que retorna false se algum campo obrigatório estiver vazio, e true caso contrário. Crie duas classes: Usuario e Produto, cada uma usando a trait e implementando regras() com campos diferentes. Teste com dados válidos e inválidos para cada classe.
Requisitos
- A trait
Validaveldeve terabstract public function regras(): array;. - O método
validardeve percorrer as regras e retornarfalsese um campo 'required' estiver vazio. - As classes
UsuarioeProdutodevem usar a trait e implementarregras(). - A saída deve mostrar
trueoufalsepara cada teste, conforme os dados.
Código inicial
<?php
// Defina a trait Validavel e as classes Usuario e Produto
$u = new Usuario();
var_dump($u->validar(['nome' => 'Ana', 'email' => 'a@b.com']));
var_dump($u->validar(['nome' => '', 'email' => 'a@b.com']));
$p = new Produto();
var_dump($p->validar(['titulo' => 'Livro', 'preco' => 10]));
var_dump($p->validar(['titulo' => '', 'preco' => 10]));
Saída esperada
bool(true)
bool(false)
bool(true)
bool(false)
Ver dica
No método validar, use $this->regras() para obter o array e verifique empty($dados[$campo]) quando a regra for 'required'.
Mostrar solução
<?php
trait Validavel {
// Método abstrato: obriga a classe a definir as regras
abstract public function regras(): array;
public function validar(array $dados): bool {
foreach ($this->regras() as $campo => $regra) {
if ($regra === 'required' && empty($dados[$campo])) {
return false;
}
}
return true;
}
}
class Usuario {
use Validavel;
public function regras(): array {
return ['nome' => 'required', 'email' => 'required'];
}
}
class Produto {
use Validavel;
public function regras(): array {
return ['titulo' => 'required', 'preco' => 'required'];
}
}
$u = new Usuario();
var_dump($u->validar(['nome' => 'Ana', 'email' => 'a@b.com']));
var_dump($u->validar(['nome' => '', 'email' => 'a@b.com']));
$p = new Produto();
var_dump($p->validar(['titulo' => 'Livro', 'preco' => 10]));
var_dump($p->validar(['titulo' => '', 'preco' => 10]));
Passo a passo
- A trait
Validaveldeclaraabstract public function regras(): array;. Isso força qualquer classe que use a trait a implementarregras(). - O método concreto
validar()percorre o array retornado por$this->regras(). - Para cada campo, se a regra for
'required'e o valor em$dadosestiver vazio (empty), retornafalseimediatamente. - Se o loop terminar sem falhas, retorna
true. Usuariousa a trait e defineregras()comnomeeemailobrigatórios.Produtousa a trait e defineregras()comtituloeprecoobrigatórios.- Os testes chamam
validar()com dados válidos e inválidos, imprimindobool(true)oubool(false)viavar_dump.
Por que funciona
A trait fornece a lógica de validação reutilizável, mas delega à classe a definição das regras específicas através do método abstrato. Isso combina reuso de código com polimorfismo: cada classe mantém sua particularidade sem duplicar o algoritmo de validação. É um exemplo clássico de trait com contrato.
Erros comuns
- Não implementar
regras()na classe: erro fatal "Class Usuario contains 1 abstract method...". - Usar
issetem vez deempty:issetretornatruepara string vazia, então a validação falharia. Useempty. - Esquecer o
use Validavel;na classe: o métodovalidarnão existirá.
Outra forma de resolver
Em vez de método abstrato, a trait poderia acessar uma propriedade $regras definida na classe. Porém, o método abstrato é mais seguro, pois o PHP garante em tempo de compilação que a classe implementou o contrato.
Saída esperada
bool(true)
bool(false)
bool(true)
bool(false)