Documentação do Symfony2
Renderizada do repositório symfony-docs-pt-BR no Github
Validação é uma tarefa muito comum em aplicações web. Dado inserido em formulário precisa ser validado. Dado também precisa ser revalidado antes de ser escrito num banco de dados ou passado a um serviço web.
Symfony2 vem acompanhado com um componente Validator que torna essa tarefa fácil e transparente. Esse componente é baseado na especificação `JSR303 Bean Validation`_. O quê ? Uma especificação Java no PHP? Você ouviu corretamente, mas não é tão ruim quanto parece. Vamos olhar como isso pode ser usado no PHP.
A melhor forma de entender validação é vê-la em ação. Para começar, suponha que você criou um bom e velho objeto PHP que você precisa usar em algum lugar da sua aplicação:
// src/Acme/BlogBundle/Entity/Author.php
namespace Acme\BlogBundle\Entity;
class Author
{
public $name;
}
Até agora, essa é somente uma classe comum que serve para alguns propósitos dentro de sua aplicação. O objetivo da validação é avisar você se um dado de um objeto é válido ou não. Para esse trabalho, você irá configura uma lista de regras (chamada constraints) em que o objeto deve seguir em ordem para ser validado. Essas regras podem ser especificadas por um número de diferentes formatos (YAML, XML, annotations, ou PHP).
Por exemplo, para garantir que a propriedade $name não é vazia, adicione o seguinte:
Tip
Propriedades protected e private podem também ser validadas, bem como os métodos
“getter” (veja validator-constraint-targets
Próximo passo, para realmente validar um objeto``Author``, use o método validate no serviço validator (classe Symfony\Component\Validator\Validator). A tarefa do validator é fácil: ler as restrições (i.e. regras) de uma classe e verificar se o dado no objeto satisfaz ou não aquelas restrições. Se a validação falhar, retorna um array de erros. Observe esse simples exemplo de dentro do controller:
use Symfony\Component\HttpFoundation\Response;
use Acme\BlogBundle\Entity\Author;
// ...
public function indexAction()
{
$author = new Author();
// ... do something to the $author object
$validator = $this->get('validator');
$errors = $validator->validate($author);
if (count($errors) > 0) {
return new Response(print_r($errors, true));
} else {
return new Response('The author is valid! Yes!');
}
}
Se a propriedade $name é vazia, você verá a seguinte mensagem de erro:
Acme\BlogBundle\Author.name:
This value should not be blank
Se você inserir um valor na propriedade name, aparecerá a feliz mensagem de sucesso.
Tip
A maior parte do tempo, você não irá interagir diretamente com o serviço validator ou precisará se preocupar sobre imprimir os erros. A maior parte do tempo, você irá usar a validação indiretamente quando lidar com dados enviados do formulário. Para mais informações, veja: ref:book-validation-forms.
Você também poderia passar o conjunto de erros em um template.
if (count($errors) > 0) {
return $this->render('AcmeBlogBundle:Author:validate.html.twig', array(
'errors' => $errors,
));
} else {
// ...
}
Dentro do template, você pode gerar a lista de erros exatamente necessária:
Note
Cada erro de validação (chamado de “constraint violation”), é representado por um objeto Symfony\Component\Validator\ConstraintViolation .
O serviço validator pode ser usado a qualquer momento para validar qualquer objeto. Na realidade, entretanto, você irá trabalhar frequentemente com o validator indiretamente enquanto trabalhar com formulário. A biblioteca Symfony’s form usa o serviço validator internamente para validar o objeto oculto após os valores terem sido enviados e fixados. As violações de restrição no objeto são convertidas em objetos FieldError que podem ser facilmente exibidos com seu formulário. O tipico fluxo de envio do formulário parece o seguinte dentro do controller:
use Acme\BlogBundle\Entity\Author;
use Acme\BlogBundle\Form\AuthorType;
use Symfony\Component\HttpFoundation\Request;
// ...
public function updateAction(Request $request)
{
$author = new Acme\BlogBundle\Entity\Author();
$form = $this->createForm(new AuthorType(), $author);
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
if ($form->isValid()) {
// the validation passed, do something with the $author object
$this->redirect($this->generateUrl('...'));
}
}
return $this->render('BlogBundle:Author:form.html.twig', array(
'form' => $form->createView(),
));
}
Note
Esse exemplo usa uma classe de formulários AuthorType , que não é mostrada aqui.
Para mais informações, veja: doc:Forms</book/forms> chapter.
O validador do Symfony2 é abilitado por padrão, mas você deve abilitar explicitamente anotações se você usar o método de anotação para especificar suas restrições:
O validator é designado para validar objtos perante restrições (i.e. regras). Em ordem para validar um objeto, simplesmente mapeie uma ou mais restrições para aquela classe e então passe para o serviço validator.
Por trás dos bastidores, uma restrição é simplesmente um objeto PHP que faz uma sentença afirmativa. Na vida real, uma restrição poderia ser: “O bolo não deve queimar”. No Symfony2, restrições são similares: elas são afirmações que uma condição é verdadeira. Dado um valor, a restriçao irá indicar a você se o valor adere ou não às regras da restrição.
Symfony2 engloba um grande número de restrições mais frequentemente usadas:
Você também pode criar sua própria restrição personalizada. Esse tópico é coberto no artigo do cookbook “Como criar uma Constraint de Validação Personalizada” .
Algumas restrições, como NotBlank, são simples como as outras, como a restrição Choice , tem várias opções de configuração disponíveis. Suponha que a classe``Author`` tenha outra propriedade, gender que possa ser configurado como “male” ou “female”:
A opção de uma restrição pode sempre ser passada como um array. Algumas restrições, entretanto, também permitem a você passar o valor de uma opção “default” no lugar do array. No cado da restrição Choice , as opções choices podem ser espeficadas dessa forma.
Isso significa simplesmente fazer a configuração da opção mais comum de uma restrição mais curta e rápida.
Se você está incerto de como especificar uma opção, ou verifique a documentação da API para a restrição ou faça de forma segura sempre passando um array de opções (o primeiro método mostrado acima).
Restrições podem ser aplicadas a uma propriedade de classe (e.g. name) ou um método getter público (e.g. getFullName). O primeiro é mais comum e fácil de usar, mas o segundo permite você especificar regras de validação mais complexas.
Validar as propriedades de uma classe é a técnica de validação mais básica.Symfony2 permite a você validar propriedades private, protected ou public. A próxima listagem mostra a você como configurar a propriedade $firstName da classe Author para ter ao menos 3 caracteres.
Restrições podem também ser aplicadas no método de retorno de um valor.Symfony2 permite a você adicionar uma restrição para qualquer método public cujo nome comec com “get” ou “is”. Nesse guia, ambos os tipos de métodos são referidos como “getters”.
O benefício dessa técnica é que permite a você validar seu objeto dinamicamente. Por exemplo, suponha que você queira ter certeza que um campo de senha não coincida com o primeiro nome do usuário (por motivos de segurança). Você pode fazer isso criando um método isPasswordLegal, e então afirmando que esse método deva retornar ‘’true’‘:
Agora, crie o método isPasswordLegal() , e inclua a lógica que você precisa:
public function isPasswordLegal()
{
return ($this->firstName != $this->password);
}
Note
Com uma visão apurada, você irá perceber que o prefixo do getter (“get” ou “is”) é omitido no mapeamento. Isso permite você mover a restrição para uma propriedade com o mesmo nome mais tarde (ou vice-versa) sem mudar sua lógica de validação.
Algumas restrições aplicam para a classe inteira ser validada. Por exemplo, a restrição Callback é uma restrição genérica que é aplicada para a própria classe. Quando a classe é validada, métodos especificados por aquela restrição são simplesmente executadas então cada um pode prover uma validação mais personalizada.
Até agora, você foi capaz de adicionar restrições a uma classe e perguntar se aquela classe passa ou não por todas as restrições definidas. Em alguns casos, entretanto, você precisará validar um objeto a somente algumas das restrições naqula classe. Para fazer isso, você pode organizar cada restrição dentro de um ou mais “grupos de validação”, e então aplicar validação a apenas um grupo de restrições.
Por exemplo, suponha que você tenha uma classe User , que é usada tanto quando um usuário registra e quando um usuário atualiza sua informações de contato posteriormente:
Com essa configuração, existem dois grupos de validação:
Para avisar o validador a usar um grupo específico, passe um ou mais nomes de trupos como um segundo argumento para o método``validate()``
$errors = $validator->validate($author, array(‘registration’));
Claro, você irá frequentemente trabalhar com validação indiretamnte por meio da biblioteca do formulário. Para informações em como usar grupos de validação dentro de formulários, veja Grupos de Validação.
Até agora, você viu como pode validar objetos inteiros. Mas às vezes, você somente quer validar um valor simples - como verificar se uma string é um endereço de e-mail válido. Isso é realmente muito fácil de fazer. De dentro do controller, parece com isso:
// add this to the top of your class use SymfonyComponentValidatorConstraintsEmail;
public function addEmailAction($email) {
$emailConstraint = new Email(); // all constraint “options” can be set this way $emailConstraint->message = ‘Invalid email address’;
// use the validator to validate the value $errorList = $this->get(‘validator’)->validateValue($email, $emailConstraint);
- if (count($errorList) == 0) {
- // this IS a valid email address, do something
- } else {
// this is not a valid email address $errorMessage = $errorList[0]->getMessage()
// do somethign with the error
}
// ...
}
Ao chamar validateValue no validador, você pode passar um valor bruto e o objeto de restrição que você com o qual você quer validar aquele valor. Uma lista completa de restrições disponíveis - bem como o nome inteiro da classe para cada restrição - está disponível em constraints reference section .
O método validateValule retorna um objeto Symfony\Component\Validator\ConstraintViolationList , que age como um array de erros. Cada erro na coleção é um objeto : class:Symfony\Component\Validator\ConstraintViolation , que contém a mensagem de erro no método getMessage dele.
O Symfony2 validator é uma ferramenta poderosa que pode ser multiplicada para garantir que o dado de qualquer objeto seja “válido”. O poder por trás da validação rside em “restrições”, que seão regras que você pode aplicar a propriedades ou métodos getter de seus objetos. E enquanto você irá usar mais frequentemente usar a validação do framework indiretamente quando usar formulários, lembre que isso pode ser usado em qualquer lugar para validar qualquer objeto.