Jump to content


Danilo Moraes

Member Since 14/01/2009
Offline Last Active 31/08/2011, 11:02
-----

Topics I've Started

Validação De Dados Com Zuuf\Validator

26/08/2011, 03:52

Bom pessoal, eu venho desenvolvendo a algum tempo, um grupo de ferramentas
chamado ZUUF. O ZUUF é apenas um conjunto de classes independentes que tem por
objetivo, servir como base para a criação de frameworks.

Eu vou apresentá-las na medida do possível e quero começar hoje pela
classe de validação: ZUUF\Validator. Todas as classes ZUUF são completamente
independentes, sendo assim, vocês podem utilizá-las em projetos a partir do
início ou projetos já em andamento, sem restrições quanto a frameworks.

Essas classes vem sendo criadas baseadas em uma funcionalidade do PHP 5.3:
namespaces. Não há muito segredo, mas estou pressupondo que vocês já sabem
trabalhar com esse recurso.

O ZUUF\Validator é bem simples. Ele é constituída de apenas uma classe e seu
código não passa de 30 linhas de código útil (tirando gets e sets e quebras de
linhas desnecessárias). No entanto, é de um poder enorme se bem utilizado.
Então vamos começar.

Baixem o código em: http://pastebin.com/CMMYgb44

Vamos a alguns conceitos dessa ferramenta. Nós primeiro registramos os "campos"
e atrelamos a eles as "validações". Um campo pode ter mais de uma validação.
Então quando eu tiver o dado a ser validado em mãos, eu apenas digo que campo
esse dado representa e as validações desse campo, serão feitas a esse dado.

Ficou confuso, né?

Vamos a um exemplo prático. Imaginem um formulário com os campos nome e idade.
Vamos imaginar as validações que podemos precisar vazer nos campos.

Campo nome:
* Deve ter entre 1 e 20 caracteres
* Deve conter apenas letras (maiúsculas ou minúsculas), espaços e pontos
Campo idade:
* Deve ser maior que 18
* Deve conter apenas números

Ok. Já entendemos a definição de campos (nome e idade) e de validações (linhas
com asterisco). O próximo passo seria registrar essas regras no ZUUF\Validator
e então, quando precisássemos validar um valor vindo pela variável
$_POST['nome'] por exemplo, nós diríamos que esse valor será validado com as
regras do campo "nome", registrado anteriormente.

Algo que o torna flexível, é que as funções para validação são vocês quem criam.

Uma validação no Validator, nada mais é que uma referência a função que será
utilizada para validar e a mensagem que será retornada caso o valor seja
inválido.

Vamos a um pouco de código.

Para começar, vamos criar um arquivo index.html e colocar nele um formulário
com os campos nome e idade. Esse formulário vai submeter para index.php:

index.html
<form action="index.php" method="post" >
    Nome: <input type="text" name="nome" /><br />
    Idade: <input type="text" name="idade" />
    <input type="submit" />
</form>

Como havia mencionado antes, as funções para validação, quem cria somos nós, o
ZUUF\Validator apenas irá chamá-las. Então vamos começar criando uma simples
função que vai validar o número de caracteres e vamos testa-la:

index.php
<?php

function caracteres1a20($nome) {
    $n = strlen($nome);
    if($n < 1 || $n > 20)
        return false;
    else
        return true;
}

if(!caracteres1a20($_POST['nome']))
    echo 'Nome deve conter entre 1 e 20 caracteres';

Se submetermos o formulário com o campo nome vazio ou com mais de 20
caracteres, ele vai mostrar a mensagem: "Nome deve conter entre 1 e 20
caracteres". Até aqui beleza.

O problema de se fazer isso aparece quando temos que fazer mais de uma
validação. Começamos a encher nosso código de if...else até que ninguém acha
mais nada ali dentro.

Vamos ver como esse mesmo código ficaria com o ZUUF\Validator:

index.php
<?php
require_once 'validator.php';

function caracteres1a20($nome) {
    $n = strlen($nome);
    if($n < 1 || $n > 20)
        return false;
    else
        return true;
}

$validator = new ZUUF\Validator;
$validator->add_field('nome',
    array('caracteres1a20', 'Nome deve conter entre 1 e 20 caracteres'));

if(!$validator->is_valid_one('nome', $_POST['nome']))
        print_r($validator->get_messages());

Nós adicionamos o campo "nome" e atribuímos a ele o nome da função que
validaria e a mensagem caso fosse inválido. is_valid_one retorna true ou false
e em caso de retornar false, get_messages vai retornar as mensagens de erro em
um array.

Vamos tornar nossa função um pouco mais dinâmica, fazendo-a receber como
parametro o número mínimo e máximo de caracteres e então passaríamos esses
valores ao definir a validação para o campo. Segue o código:

index.php
<?php
require_once 'validator.php';

function largura($palavra, $min = 0, $max = null) {
    $largura_palavra = strlen($palavra);

    if($max === null) {
        if($largura_palavra < $min)
            return false;
    } else
        if($largura_palavra < $min || $largura_palavra > $max)
            return false;

    return true;
}

$validator = new ZUUF\Validator;
$validator->add_field('nome',
   array('largura', array(1, 20), 'Nome deve conter entre 1 e 20 caracteres'));

if(!$validator->is_valid_one('nome', $_POST['nome']))
    print_r($validator->get_messages());

Percebam que renomeei a função para largura. Essa nova função é bem simples. Se
receber apenas o valos mínimo, valida apenas pelo mínimo. Se receber os dois,
valida pelos dois. Para passar os parâmetros na validação, apenas passe-os
dentro de um array, na segunda posição, como no código.

Um exemplo validando também as letras no nome:

index.php
<?php
require_once 'validator.php';

function largura($palavra, $min = 0, $max = null) {
    $largura_palavra = strlen($palavra);

    if($max === null) {
        if($largura_palavra < $min)
            return false;
    } else
        if($largura_palavra < $min || $largura_palavra > $max)
            return false;

    return true;
}

function letras($palavra) {
    if(preg_match('%^[a-zA-Z \.]*$%', $palavra))
        return true;
    else
        return false;
}

$validator = new ZUUF\Validator;
$validator->add_field('nome',
  array('largura', array(1, 20), 'Nome deve conter entre 1 e 20 caracteres'));
$validator->add_field('nome',
  array('letras', 'Deve conter apenas letras (maiúsculas ou minúsculas), espaços e pontos'));

if(!$validator->is_valid_one('nome', $_POST['nome']))
    print_r($validator->get_messages());

Quando se precisa validar mais de um campo por vez, o ZUUF\Validator trás uma
facilidade com a função is_valid_all. Vejam o exemplo com o campo idade:

index.php
<?php
require_once 'validator.php';

function largura($palavra, $min = 0, $max = null) {
    $largura_palavra = strlen($palavra);

    if($max === null) {
        if($largura_palavra < $min)
            return false;
    } else
        if($largura_palavra < $min || $largura_palavra > $max)
            return false;

    return true;
}

function letras($palavra) {
    if(preg_match('%^[a-zA-Z \.]*$%', $palavra))
        return true;
    else
        return false;
}

function numeros($palavra) {
    if(preg_match('%^[0-9]*$%', $palavra))
        return true;
    else
        return false;
}

function minimo($valor, $min = 0) {

    if($valor < $min)
        return false;
    else
        return true;
}

$validator = new ZUUF\Validator;
$validator->add_field('nome',
  array('largura', array(1, 20), 'Nome deve conter entre 1 e 20 caracteres'));
$validator->add_field('nome',
  array('letras', 'Deve conter apenas letras (maiúsculas ou minúsculas), espaços e pontos'));
$validator->add_field('idade',
  array('minimo', array(18), 'Idade deve ser maior que 18'));
$validator->add_field('idade',
  array('numeros', 'Deve conter apenas números'));

if(!$validator->is_valid_all(array('nome' => $_POST['nome'], 'idade' => $_POST['idade'])))
    print_r($validator->get_messages());

O método is_valid_all retorna os dados um pouco diferente. Retorna um array onde a chave é o nome
do campo e o valor, é o array com as mensagens de erro. Então você decide como apresentá-las. Aqui
segue um exemplo mais enxuto de como utilizar essa classe para o que fizemos:

index.php
<?php
require_once 'validator.php';

function rg($valor, $min = 0, $max = null) {//range de falores

    if($max === null) {
        if($valor < $min)
            return false;
    } else
        if($valor < $min || $valor > $max)
            return false;

    return true;
}

function largura($palavra, $min = 0, $max = null) {
    return rg(strlen($palavra), $min, $max);
}

function alpha($palavra) {
    if(preg_match('%^[a-zA-ZãÃáÁàÀêÊéÉèÈíÍìÌôÔõÕóÓòÒúÚùÙûÛçÇ \.]*$%', $palavra))
        return true;
    else
        return false;
}

function numeros($palavra) {
    if(preg_match('%^[0-9]*$%', $palavra))
        return true;
    else
        return false;
}

function regex($palavra, $regex) {
    if(preg_match("%$regex%", $palavra))
        return true;
    else
        return false;
}


$validator = new ZUUF\Validator;
$validator->add_field('nome',
  array('largura', array(1, 20), 'Nome deve conter entre 1 e 20 caracteres'));
$validator->add_field('nome',
  array('alpha', 'Deve conter apenas letras (maiúsculas ou minúsculas), espaços e pontos'));
$validator->add_field('idade', array('rg', array(18), 'Idade deve ser maior que 18'));
$validator->add_field('idade', array('regex', array('^[0-9]*$'), 'Deve conter apenas números'));

if(!$validator->is_valid_all(array('nome' => $_POST['nome'], 'idade' => $_POST['idade'])))
    print_r($validator->get_messages());

Neste exemplo ainda criei a função regex para mostrar como essa classe pode se tornar extensível.
Um útimo exemplo serve para mostrar mais uma possíbilidade. Imaginem que eu quero mostrar uma
mensagem caso a pessoa tenha digitado uma idade menor que 18 e outra mensagem caso ela tenha
digitado um valor maior que 30.

index.php
<?php
require_once 'validator.php';

function rg($valor, $min = 0, $max = null) {//range de falores

    if($max === null) {
        if($valor < $min)
            return false;
    } else
        if($valor < $min || $valor > $max)
            return false;

    return true;
}


$validator = new ZUUF\Validator;
$validator->add_field('idade', array('rg', array(18), 'Idade deve ser maior que 18'));
$validator->add_field('idade', array('rg', array(null, 30), 'Idade deve ser menor que 30'));

if(!$validator->is_valid_one('idade', $_POST['idade']))
    print_r($validator->get_messages());

Percebam que as possibilidades agora dependem da criatividade com as funções. Para deixar mais
organizado, poderiam criar um arquivo apenas com as funções para validação e incluí-los sempre que
usar a classe ZUUF\Validator.

Se preferirem criar classes com as validações, lembrem-se que quando estamos passando o nome da
função, estamos passando um callback. Para passar um método de classe ou de objeto, basta passar
ali o callback da maneira correta. Ex: array($obj, 'metodo'). Vide manual do php para mais exemplos.

Acho que é isso. Deixem comentários.

Aliasmatch Condicional

13/07/2011, 11:57

Buenas pessoal, estou precisando de uma luz.
Vejam minha configuração de virtual host:
<VirtualHost *:80>

	ServerAdmin clientarcrm@localhost
	ServerName clientar.com.br
	ServerAlias *.clientar.com.br
	DocumentRoot /home/danilo/Projetos/clientarcrm/
	CustomLog /var/log/apache2/clientar-access.log combined	

	<Directory /home/danilo/Projetos/clientarcrm/>		
		Options FollowSymLinks
		AllowOverride none	

		RewriteEngine On
		RewriteRule ^(.*)$ index.php [L]
	</Directory>

	AliasMatch ^/([^/]+)/public(.*) /home/danilo/Projetos/clientarcrm/system/application/standart.packets/$1/public$2

	<DirectoryMatch "^/home/danilo/Projetos/clientarcrm/system/application/standart\.packets/.+/public/*">
		RewriteEngine On
		RewriteCond %{REQUEST_FILENAME} !-f
		RewriteRule ^(.*)$ /home/danilo/Projetos/clientarcrm/index.php [L]

	</DirectoryMatch>
</VirtualHost>

Bom, nele eu fiz redirecionar qualquer requisição para o arquivo index.php a não ser que o arquivo esteja naquele diretório public e realmente exista. Fiz isso para que o próprio apache possa retornar os arquivos css, javascript ou imagem que forem usados no html. Até aqui está tudo funcionando perfeitamente bem. O que estou precisando agora é de algo como um teste condicional.
Eu tenho duas pastas diferentes mas geralmente com o mesmo conteúdo. Uma é: /home/danilo/Projetos/clientarcrm/system/application/standart.packets/ e a outra: /home/danilo/Projetos/clientarcrm/system/application/extension.packets/

O que preciso é saber se existe um diretório dentro de extension.packets. Se existir, ele retorna os arquivos da pasta public dentro dele. Se não existir, ele retorna os arquivos de dentro da pasta public de standart.packets.

Exemplo:
http://clientar.clie.../css/tabela.css

preciso que ele tente retornar o arquivo /home/danilo/Projetos/clientarcrm/system/application/estension.packets/usuario/public/css/tabela.css se esse arquivo não existir, então ele me retorna o arquivo em: /home/danilo/Projetos/clientarcrm/system/application/standart.packets/usuario/public/css/tabela.css

Procura em extension.packets/ e depois em standart.packets/

Alguém poderia me ajudar com isso?
Muito obrigado desde já.

IPB Skin By Virteq