quarta-feira, janeiro 23, 2008

Validando em PHP Expressões Regulares

Trabalhar com PHP é fácil, pois ele é poderoso e simples.

Para você fazer um teste se uma variável possui o padrão que você deseja (máscara), basta usar a função ereg ou eregi, que retorna TRUE (corresponde) ou FALSE (não corresponde)
A função ereg é case sensitive, ou seja, diferencia maiúsculas de minúsculas; já a eregi ignora essa diferença.

Exemplo:

$meus = (isset($_GET['meus'])) ? trim($_GET['meus']) : '';
if (ereg("[^a-zA-Z]",$meus)) {
$meus = '';
}

Acima eu verifico se a variável $_GET['meus'] foi inicializada; se sim atribuo ela à minha variável meus, senão atribuo vazio. Depois (eu poderia colocar junto com a verificação acima, mas assim fica mais fácil de enxergar) eu verifico se a variável é composta somente por letras. Sepossuir em seu conteúdo algo "não letra" (o não é simbolizado pelo "^" no início do bloco entre colchetes), atribuo vazio à variável (se for composta por letras... mantenho ela como está).
Poderíamos usar a eregi, que funciona igualzinho, apenas com a diferença que falei anteriormente.

Seguem uma função que uso para validar variáveis. Dá para ser incrementada e modificada, por isso, poste aqui se fizer algum melhoramento!

function validarCampo($str,$tipo,$tam) {
$padrao = '';
if (strlen($str)<=0) {return FALSE;}
if (!is_numeric($tam)) {return FALSE;}
if (strlen($str)>$tam) {return FALSE;}
if ($tipo=='n1') { $padrao = '^[0-9]+$'; } //numerico
if ($tipo=='n2') { $padrao = '^[0-9 ]+$'; } //numerico com espaços
if ($tipo=='fl') { $padrao = '^[+-]?(([0-9]+|[0-9]{1,3}(\.[0-9]{3})+)(\,[0-9]*)?|\,[0-9]+)$'; } //float
if ($tipo=='a1') { $padrao = '^[A-Za-zÀ-ú]*$'; } // alfa
if ($tipo=='a2') { $padrao = '^[A-Za-zÀ-ú0-9\&\; ]*$'; } // string - alfanumerico
if ($tipo=='a3') { $padrao = '^[A-Za-z0-9]*$'; } // string - alfanumerico sem acentuação
if ($tipo=='a4') { $padrao = '^[A-Za-zÀ-ú0-9@#%!&\*\?\)\(\$\}\{\+\.\-\,\;\: ]*$'; } // string - alfanumerico com caracteres especiais
if ($tipo=='a5') { $padrao = '^[A-Za-zÀ-ú0-9@#%!&\*\?\)\(\$\}\{\+\.\-\_\,\;\:\n\r ]*$'; } // string - alfanumerico com caracteres especiais
if ($tipo=='ht') { $padrao = '^[A-Za-zÀ-ú0-9@#%!&\*\?\)\(\$\}\{\+\.\-\_\,\;\:\n\r\<\>\/ ]*$'; } // caracteres de um trecho HTML
if ($tipo=='em') { $padrao = '^[0-9a-zA-Z]+[\_\-\.]?[0-9a-zA-Z]+@(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9]\.)+[A-Za-z]{2,6}|\[[0-9]{1,3}(\.[0-9]{1,3}){3}\])$'; } //email
if ($tipo=='u1') { $padrao = '^((ht|f)tp(s?)\:\/\/|~\/|\/){1}([0-9a-zA-Z]+:[0-9a-zA-Z]+@)?([a-zA-Z]{1}([0-9a-zA-Z-]+\.?)*(\.[0-9a-zA-Z]{2,5}){1})$'; } //url
if ($tipo=='u2') { $padrao = '^((ht|f)tp(s?)\:\/\/|~\/|\/){1}([0-9a-zA-Z]+:[0-9a-zA-Z]+@)?(([a-zA-Z]{1}([0-9a-zA-Z-]+\.?)*(\.[0-9a-zA-Z]{2,5}){1})(:[0-9]{1,5})?)?((\/?[0-9a-zA-Z_-]+\/)+|\/?)([0-9a-zA-Z]+([0-9a-zA-Z_-]?[0-9a-zA-Z]+)?\.[0-9a-zA-Z]{3,4})?([,][0-9a-zA-Z]+)*((\?[0-9a-zA-Z]+=[0-9a-zA-Z]+)?(&[0-9a-zA-Z]+=[0-9a-zA-Z]+)*([,][0-9a-zA-Z]*)*)?$'; } //url com subpasta e arquivo
if ($tipo=='t1') { $padrao = '^[0-9]{10}$'; } //telefone com DDD
if ($tipo=='t2') { $padrao = '^[0-9]{12}$'; } //telefone com DDD e país
if ($tipo=='t3') { $padrao = '^[0-9]{2} [0-9]{2} [0-9]{4}\-[0-9]{4}$'; } //telefone com DDD e país formatado 55 13 9999-9999
if ($tipo=='t4') { $padrao = '^0800[0-9]{6,7}$'; } //telefone 0800 sem espaços (080000(0)0000)
if ($tipo=='t5') { $padrao = '^0800\-[0-9]{2,3}\-[0-9]{4}$'; } //telefone 0800 formatado 0800-00(0)-0000
if ($tipo=='ip') { $padrao = '^[0-9]{3}.[0-9]{3}.[0-9]{3}.[0-9]{3}$'; } //ip
if ($tipo=='mo') { $padrao = '^\[0-9]{1,3}(\.[0-9]{3})*\,[0-9]{2}$'; } //moeda
if ($tipo=='d1') { $padrao = '^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$'; } //data no formato DD/MM/AAAA
if ($tipo=='d2') { $padrao = '^[0-9]{4}\/[0-9]{2}\/[0-9]{2}$'; } //data no formato AAAA/MM/DD
return ereg($padrao,$str);
}

Essa função recebe uma valor (uma string), um tipo de campo para validar e um tamanho máximo que este valor pode ter. Se não bate com o padrão ou for maior que o tamanho permitido, retorna FALSE.
Ela usa padrões de formatação também, como por exemplo "/" para data. Poderíamos usar "/" ou "-". Ficaria algo como '^[0-9]{4}[\/\-][0-9]{2}[\/\-][0-9]{2}$'. Aí vai do gosto do freguês.

Obs: o caractere "^" no início da expressão, indica que ela deve começar com aquele padrão, e o caractere "$" indica que deve terminar com o padrão também. Nesses casos, o conteúdo da variável deve seguir exatamente o padrão estipulado em seu todo. Se não colocássemos estes caracteres, esse padrão poderia ocorrer em qualquer lugar do campo/variável.
Se o caractere "^" aparecer dentro de um bloco "[]", ele significa NÃO.

Os que demoraram mais, através de pesquisas e ajustes foi criação (se assim posso dizer) do padrão de URL e o de e-mail, porque nos testes sempre aparecia algo novo... por isso, qualquer falha em qualquer padrão avise/comente!

Um bom guia é http://guia-er.sf.net, do Aurélio.

Abraço!!!

7 comentários:

helderh disse...

Ola Daniel , encontrei vc no Forum do MAGENTO e preciso conversar com vc sobre um projeto relacionado ao mesmo.
Poderia me adicionar no seu gtalk? Meu eh helderdiv@gmail.com
grato, Helder

Unknown disse...

Olá Daniel,

Verificando seu código e adaptando ao meu sistema, o padrão data DD/MM/AAAA está dando erro quando colocado a data com o zero (0) no terceiro elemento (1905), ou colocado ano com dois e três zeros no final (2000, 2100).

Gostaria de uma solução, pois estou procurando e ainda não encontrei.

Att
Ariel Bianchi.

Daniel disse...

Ariel,

eu executei essa função em um laço assim:

for ($i=1900;$i<2100;$i++) {
echo "[p]$i: ".validarCampo('14/07/'.$i,'d1',10)."[/p]";
}

de 1900 a 2100 e deu tudo 1 (true)

Poste o código para a gente ver

Unknown disse...

Daniel,

Estou usando dessa forma, pois a cadas valor nos parenteses uso como registro para validação.

(!ereg("([0-9]{2})\/([0-9]{2})\/([0-9]{4})", $data, $registros)).

Tentei colocar:
- ^ e $ de cada parenteses;
- Toda a função dentro de outro parenteses com ^ e $.

Daniel disse...

OK Ariel, vamos lá!

O ^ e $ são da string por inteiro, então se você quer validar a string, deve usá-los em torno do padrão a ser encontrado.
Você está colocando uma exclamação, ou seja, se NÃO conferir com o padrão, faça tal coisa.

Para armazenar no vetor utilizando os índices da expressão regular através dos parênteses (lembre-se que 0 é a string inteira e de 1 a 9 são os pedaços entre parênteses), usa-se o terceiro parâmetro que é um vetor.
Para armazenar nele em que você pode exibir a data da maneira que quiser, você pergunta se CONFERE com o padrão.

Seria assim:

if (ereg ("^([0-9]{2})[\/\-]([0-9]{2})[\/\-]([0-9]{4})$", $data, $registros)) {
echo $registros[1].'/'.$registros[2].'/'.$registros[3];
} else {
echo "Data inválida: $data";
}

Se conferir com o padrão, joga no vetor e mostra, senão, fala que é inválida. Assim se houver espaços no fim ou no começo da string, dará falso. use a função trim() para evitar isso, ou então não use os ^ e $, mas isso pode fazer com que a string 'basbausa05/05/2008Daniel' seja válida.

Faça esse teste e mantenha-me informado :D

Ariel Iaêrlë disse...

Desculpe a demora,

Utlizei o formato:
([0-9]{2})[\/\-]([0-9]{2})[\/\-]([0-9]{4})

E tudo ocorreu bem.

Porém na função do registro eu verifico se apenas contem número.

Att
Ariel Bianchi

Engenharia de Software disse...

Show de bola seu código, perfeito, cobriu minhas necessidades, obrigado!!!!!!!!!!!!!