8.1 – Validações
Escolhe um trabalho de que você goste e não terá que trabalhar nem um dia na sua vida.
Confúcio
(Mas se não encontrar um de que você goste, empenhe-se no que você tem no momento e fique atento para encontrar um de que gosta)
Ribamar FS
A validação no Cake é feita no Model, mais especificamente na classe Table
Exemplo, o nosso aplicativo cliente:
src\Model\Table\ClientesTable.php
…
public function validationDefault(Validator $validator)
{
$validator
->integer('id')
->allowEmptyString('id', 'create');
$validator
->scalar('nome')
->maxLength('nome', 45)
->requirePresence('nome', 'create')
->allowEmptyString('nome', false);
$validator
->email('email')
->requirePresence('email', 'create')
->allowEmptyString('email', false);
$validator
->date('data_nasc')
->requirePresence('data_nasc', 'create')
->allowEmptyDate('data_nasc', false);
$validator
->scalar('cpf')
->maxLength('cpf', 11)
->requirePresence('cpf', 'create')
->allowEmptyString('cpf', false);
return $validator;
}
/**
* Returns a rules checker object that will be used for validating
* application integrity.
*
* @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
* @return \Cake\ORM\RulesChecker
*/
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->isUnique(['email']));
return $rules;
}
…
O método validationDefault() diz ao CakePHP como validar seus dados quando o método save() no action no controller for solicitado.
Observações:
- Vejamos o campo nome:
->maxLength('nome', 45)
->requirePresence('nome', 'create')
->allowEmptyString('nome', false);
De onde o Cake tirou este tamanho máximo de 45?
Da nossa tabela. Veja que lá temos varchar(45).
De onde ele tirou que deve requerer a presença na criação de novos registros?
Também da tabela, onde viu NOT NULL, o que assegura a linha abaixo para não permitir vazio.
Desde que tenhamos usado o método Cake\View\Helper\FormHelper::input() do FormHelper para criar nossos elementos, nossas mensagens de alerta da validação serão exibidas automaticamente.
Validação para o CPF
Baixar o repositório para a validação de:
https://github.com/gspaiva/cpfvalidator
Ajustar num campo cujo nome seja "cpf" para que nossa ClientesModel seja:
<?php
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class ClientesTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('clientes');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
}
public function validationDefault(Validator $validator)
{
$validator
->integer('id')
->allowEmptyString('id', 'create');
$validator
->scalar('nome')
->maxLength('nome', 45)
->requirePresence('nome', 'create')
->allowEmptyString('nome', false);
$validator
->email('email')
->requirePresence('email', 'create')
->allowEmptyString('email', false);
$validator
->date('data_nasc')
->requirePresence('data_nasc', 'create')
->allowEmptyDate('data_nasc', false);
$validator
->scalar('cpf')
->maxLength('cpf', 11)
->requirePresence('cpf', 'create')
->allowEmptyString('cpf', false);
$validator
->add('cpf','custom',
['rule'=>
function($cpf)
{
// Verifica se um número foi informado
if(empty($cpf)) {
return false;
}
// Elimina possivel mascara
$cpf = preg_replace('[^0-9]', '', $cpf);
$cpf = str_pad($cpf, 11, '0', STR_PAD_LEFT);
// Verifica se o numero de digitos informados é igual a 11
if (strlen($cpf) != 11) {
return false;
}
// Verifica se nenhuma das sequências invalidas abaixo foi digitada
else if ($cpf == '00000000000' ||
$cpf == '11111111111' ||
$cpf == '22222222222' ||
$cpf == '33333333333' ||
$cpf == '44444444444' ||
$cpf == '55555555555' ||
$cpf == '66666666666' ||
$cpf == '77777777777' ||
$cpf == '88888888888' ||
$cpf == '99999999999') {
return false;
// Calcula os digitos verificadores para verificar se o cpf é valido
} else {
for ($t = 9; $t < 11; $t++) {
for ($d = 0, $c = 0; $c < $t; $c++) {
$d += $cpf{$c} * (($t + 1) - $c);
}
$d = ((10 * $d) % 11) % 10;
if ($cpf{$c} != $d) {
return false;
}
}
return true;
}
},
// Caso retorne falso ele vai retornar uma mensagem falando que é inválido
'message'=>'=== CPF INVÁLIDO ==='
]);
return $validator;
}
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->isUnique(['email']));
return $rules;
}
}
Customizando as mensagens de erro do Cake
Caso ache necessário pode customizar o design das mensagens de erro.
Edite o arquivo:
webroot/css/style.css
E altere o código de do seletor .form .error-message para este:
.form .error-message {
display: block;
padding: 0.375rem 0.5625rem 0.5625rem;
margin-top: -1px;
margin-bottom: 1rem;
font-size: 1rem;
font-weight: normal;
font-style: italic;
color: #FF0000;
}
Outras Validações Customizadas
$validator->add('nascimento',[
'notEmptyCheck'=>[
'rule'=>[$this,'notEmptyNascimento'],
'provider'=>'table',
'message'=>'Favor selecionar uma data de nascimento'
]
]);
return $validator;
}
public function notEmptyNascimento($value,$context){
if(empty($context['data']['nascimento'])) {
return false;
} else {
return true;
}
}
Validação nos Forms
Para tirar proveito dos recursos de validação do Cake, você vai precisar usar o Form helper em suas views para criar formulários e nunca criar diretamente código HTML. O Cake\View\Helper\FormHelper está disponível por padrão em todas as views pelo uso do $this->Form.
Basta usar $this->Form->...
Cuidados com o banco de dados
Uma preocupação com a segurança deve levar a um cuidado com a criação das tabelas no banco de dados com vários detalhes:
- Relacionamentos sempre que for importante
- Tipo de dados de cada campo selecionado com critério
- Tamanho dos campos
- Quantidade de campos
- Constraints de cada campo
Criando nossas próprias regras de validação
O sistema de validação do Cake é rico e flexível e ainda permite que criemos nossas próprias regras de validação. Uma forma simples é usando Expressões Regulares.
Desde que estejamos usando o método Cake\View\Helper\FormHelper::control() do FormHelper para criar os elementos do form, nossas mensagens de erro de validação serão mostradas automaticamente.
Para tirar proveito dos recursos de validação do Cake, você vai precisar usar o Form helper em suas views.
Validações Customizadas
Validação de senha:
/**
* Checks password for a single instance of each:
* number, uppercase, lowercase, and special character
*
* @param type $password
* @param array $context
* @return boolean
*/
public function checkCharacters($password, array $context)
{
// number
if (!preg_match("#[0-9]#", $password)) {
return false;
}
// Uppercase
if (!preg_match("#[A-Z]#", $password)) {
return false;
}
// lowercase
if (!preg_match("#[a-z]#", $password)) {
return false;
}
// special characters
if (!preg_match("#\W+#", $password) ) {
return false;
}
return true;
}
$validator
->requirePresence('password', 'create')
->notEmpty('password', 'You must enter a password', 'create')
->add('password', [
'length' => [
'rule' => ['minLength', 8],
'message' => 'Passwords must be at least 8 characters long.',
]
])
->add('password', 'custom', [
'rule' => [$this, 'checkCharacters'],
'message' => 'The password must contain 1 number, 1 uppercase, 1 lowercase, and 1 special character'
]);
Validação Condicional
Baseado no Entity
$rules->add(function ($entity, $options) use($rules) {
if ($entity->role == 'admin') {
$rule = $rules->existsIn('user_id', 'Admins');
return $rule($entity, $options);
}
if ($entity->role == 'user') {
$rule = $rules->existsIn('user_id', 'Users');
return $rule($entity, $options);
}
return false;
}, 'userExists');
Detalhes em
Comments fornecido por CComment