Validar é uma característica dos modelos Laravel Eloquent que garante que os modelos atendam aos seus critérios de validação antes de serem salvos. Caso não sejam considerados válidos o modelo não será salvo e os erros de validação serão disponibilizados.
A validação permite vários conjuntos de regras, injetando o ID do modelo em regras de validação unique
e gerando exceções em validações com falha. É pequeno e flexível para caber perfeitamente no seu fluxo de trabalho e ajudar você a salvar apenas dados válidos.
Quer usar a validação no Laravel 4.2+? Dê uma olhada na ramificação 0.10.x para documentação e instruções de instalação.
A versão Laravel 4.2 é mais adequada para validação de formulários; ele suporta mensagens de validação personalizadas, regras de confirmação e vários conjuntos de regras. Como o Laravel 5.0 possui validação FormRequest
a Validação agora foi projetada para manter seus dados principais válidos e deixar a validação do formulário para a estrutura.
Quer usar a validação no Laravel 5.0 a 5.2? Dê uma olhada no branch 2.x para documentação e instruções de instalação.
A versão Laravel 5.0 - 5.2 usou um contrato ValidationException
obsoleto da estrutura Laravel. Para o Laravel 5.3, agora estendemos a validação principal ValidationException
, o que significa que a estrutura irá redirecionar automaticamente de volta com erros quando ocorrer um erro de validação, assim como faria um FormRequest
.
Continue lendo - estas instruções são para você!
Basta ir ao diretório do seu projeto onde o arquivo composer.json
está localizado e digitar:
compositor requer watson/validação
Veja as instruções de instalação do Laravel 4.2+. Veja as instruções de instalação do Laravel 5.0 - 5.2.
Primeiro, adicione a característica ao seu modelo e adicione suas regras e mensagens de validação conforme necessário.
use WatsonValidatingValidatingTrait;class Post estende Eloquent { usar ValidatingTrait; protegido $rules = [ 'title' => 'required', 'slug' => 'required|unique:posts,slug', 'content' => 'required' ]; }
Você também pode adicionar a característica a um BaseModel
se estiver usando um e ele funcionará em todos os modelos que se estendem a partir dele, caso contrário, você pode simplesmente estender WatsonValidatingValidatingModel
em vez de Eloquent
.
Nota: você precisará definir a propriedade $rules
em qualquer modelo que se estenda de um BaseModel
que usa a característica ou, de outra forma, definir uma matriz vazia como $rules
para o BaseModel
. Caso contrário, você inevitavelmente terminará com LogicException with message 'Relationship method must return an object of type IlluminateDatabaseEloquentRelationsRelation'
.
Agora você tem acesso a algumas funcionalidades agradáveis.
// Verifica se o modelo é válido ou não.$post->isValid(); // true// Ou verifique se é inválido ou não.$post->isInvalid(); // false// Depois de determinar a validade do modelo, // você pode obter os erros.$post->getErrors(); //erros MessageBag
A validação do modelo também se torna muito simples.
if ( ! $post->save()) {// Oops.return redirect()->route('posts.create') ->withErrors($post->getErrors()) ->comInput(); }return redirecionamento()->route('posts.show', $post->id) ->withSuccess("Sua postagem foi salva com sucesso.");
Caso contrário, se preferir usar exceções ao validar modelos, você pode usar o método saveOrFail()
. Agora, uma exceção será gerada quando você tentar salvar um modelo inválido.
$post->saveOrFail();
Você não precisa capturar a exceção , se não quiser. O Laravel sabe como lidar com uma ValidationException
e irá redirecionar automaticamente de volta com entrada de formulário e erros. Se você quiser cuidar disso sozinho, você pode.
tente {$post->saveOrFail(); } catch (WatsonValidatingValidationException $e) {$errors = $e->getErrors();return redirect()->route('posts.create') ->withErrors($erros) ->comInput(); }
Observe que você pode simplesmente passar a exceção para o método withErrors()
como withErrors($e)
e o Laravel saberá como lidar com isso.
Se você estiver usando o modelo e desejar realizar um salvamento que ignore a validação, você pode. Isso retornará o mesmo resultado como se você chamasse save()
em um modelo sem a característica.
$post->forceSave();
Se você preferir que exceções sejam lançadas por padrão ao usar o método save()
em vez de usar saveOrFail()
você pode simplesmente definir a seguinte propriedade em seu modelo ou BaseModel
.
/** * Se o modelo deve lançar uma ValidationException se * falhar na validação. Se não for definido, o padrão será falso. * * @var boolean */protected $throwValidationExceptions = true;
Se desejar realizar um salvamento único usando exceções ou valores de retorno, você pode usar os métodos saveOrFail()
e saveOrReturn
.
Para mostrar mensagens de erro de validação personalizadas, basta adicionar a propriedade $validationMessages
ao seu modelo.
/** * Mensagens de validação a serem passadas ao validador. * * @var array */protected $validationMessages = ['slug.unique' => "Outro post já está usando esse slug."];
Você deve ter notado que estamos usando a regra unique
no slug, o que não funcionaria se estivéssemos atualizando um modelo persistente. Felizmente, a Validação cuidará disso para você e anexará a chave primária do modelo à regra para que a regra funcione conforme o esperado; ignorando o modelo atual.
Você pode ajustar essa funcionalidade definindo a propriedade $injectUniqueIdentifier
em seu modelo.
/** * Se o modelo deve injetar seu identificador nas * regras de validação exclusivas antes de tentar a validação. Se esta propriedade * não estiver definida no modelo, o padrão será verdadeiro. * * @var boolean */protected $injectUniqueIdentifier = true;
Pronto para uso, oferecemos suporte à regra unique
fornecida pelo Laravel. Também apoiamos a popular regra felixkiss/uniquewith-validator, mas você precisará aceitá-la. Basta adicionar use WatsonValidatingInjectorsUniqueWithInjector
depois de importar a característica de validação.
Também é fácil oferecer suporte a regras de injeção adicionais, se desejar. Digamos que você queira oferecer suporte a uma regra adicional chamada unique_ids
, que simplesmente usa a chave primária do modelo (por qualquer motivo). Você só precisa adicionar uma regra camel-case que aceite quaisquer parâmetros existentes e o nome do campo e retorne a regra de substituição.
/** * Prepare uma regra unique_ids, adicionando um identificador de modelo, se necessário. * * @param array $parâmetros * @param string $field * @return string */função protegida prepareUniqueIdsRule($parameters, $field) {// Execute uma substituição apenas se o modelo tiver sido persistido.if ($this->exists) {return 'unique_ids:' . $this->getKey(); }retornar 'IDs_únicos'; }
Neste caso se o modelo foi salvo e possui chave primária 10
, a regra unique_ids
será substituída por unique_ids:10
.
Vários eventos são disparados pela característica durante o processo de validação, aos quais você pode se conectar para impactar o processo de validação.
Para se conectar, primeiro você precisa adicionar a propriedade $observeables
ao seu modelo (ou modelo base). Isso simplesmente permite ao Eloquent saber que seu modelo pode responder a esses eventos.
/** * Eventos observáveis expostos pelo usuário * * @var array */protected $observables = ['validating', 'validated'];
Quando a validação estiver prestes a ocorrer, o evento eloquent.validating: ModelName
será disparado, onde o parâmetro $event
estará saving
ou restoring
. Por exemplo, se você estivesse atualizando um modelo com namespace AppUser
o evento seria eloquent.validating: AppUser
. Se você ouvir qualquer um desses eventos e retornar um valor, poderá impedir que a validação ocorra completamente.
Event::listen('eloquent.validating:*', function($model, $event) {// Validação de roleta pseudo-russa.if (rand(1, 6) === 1) {return false; } });
Após a validação ocorrer, há também uma série de eventos validated
aos quais você pode se conectar, para os eventos passed
, failed
e skipped
. Para o exemplo acima com falha na validação, você pode obter o evento eloquent.validated: AppUser
.
Atualmente existe um bug no Laravel (veja o problema #1181) que impede que eventos de modelo sejam disparados mais de uma vez em um conjunto de testes. Isso significa que o primeiro teste que usa testes de modelo será aprovado, mas todos os testes subsequentes falharão. Existem algumas soluções temporárias listadas nesse tópico que você pode usar para fazer seus testes passarem enquanto isso.
Como o Laravel mudou para o Liferaft com o propósito de rastrear bugs e pull requests, o problema mencionado acima pode não estar disponível. Este Gist tem um exemplo TestCase.php
que mostra como redefinir os eventos de todos os seus modelos entre os testes para que funcionem conforme o esperado.
Existem várias maneiras de usar o modelo de validação em seus controladores, no entanto, aqui está um exemplo que faz uso do novo FormRequest no Laravel 5 (se você quiser ver outro exemplo de controlador sem o FormRequest, verifique a versão 4.2+ deste pacote.
Este exemplo mantém seu código limpo, permitindo que FormRequest lide com a validação do formulário e o modelo lide com sua própria validação. Ao habilitar exceções de validação, você pode reduzir o código repetitivo do controlador (blocos try/catch) e lidar com exceções de validação de modelo globalmente (suas solicitações de formulário devem manter seus modelos válidos, portanto, se seu modelo se tornar inválido, será um evento excepcional ).
<?php namespace AppHttpControllers;use AppHttpRequestsPostFormRequest;use IlluminateRoutingController;class PostsController estende o controlador {protegido $post;função pública __construct(Post $post) {$this->postagem = $postagem; }// ...armazenamento de função pública(PostFormRequest $request) {// A postagem lançará uma exceção se não for válida.$post = $this->post->create($request->input());// A postagem foi salva com sucesso.return redirect()->route( 'postagens.show', $post); } }
Você pode então capturar uma exceção de validação de modelo em seu app/Exceptions/Handler.php
e lidar com ela conforme necessário.
renderização de função pública ($ solicitação, Exceção $ e) {if ($e instanceof WatsonValidatingValidationException) {return back()->withErrors($e)->withInput(); }parent::render($request, $e); }