8.1 - Validações

Imprimir

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

https://book.cakephp.org/3.0/en/orm/validation.html

https://book.cakephp.org/3.0/pt/orm/validation.html