Archive for the ‘Validação’ Category

Evitando múltiplos posts com session

Monday, March 10th, 2008

Muitos desenvolvedores já se depararam com a situação de que usuários impacientes enviam formulários dezenas de vezes, e isso realmente incomoda, pois aparecem vários registros idênticos.

Uma forma de solucionar tal problema seria usando session. No momento do envio, salva algo que identifique(que chamarei de identidade) o formulário na SESSION, e sempre que for enviar algo, verifica se a identidade da session bate com a do fomulário enviado, se bater, o sistema impede que o formulário seja enviado novamente.

No caso de formulários de e-mail, eu particularmente uso como identidade a mensagem do e-mail criptografada por md5, visto que reduz significativamente o tamanho do que será guardado na session.

Bom, vamos aos códigos:


session_start();

$md5Mensagem = md5($_POST['mensagem']);
if(isset($_SESSION['md5Mensagem'] && $md5Mensagem == $_SESSION['md5Mensagem']){
     echo 'Esta mensagem já foi enviada';
} else {
     if(ENVIA_MENSAGEM){
          $_SESSION['md5Mensagem'] = $md5Mensagem;
          echo 'Mensagem enviada com sucesso';
     } else echo 'Mensagem não foi enviada';
}

O código acima está bem simplificado, eu encapsulei o processo de enviar a mensagem (função mail, gravar no banco, ou qualquer outro método) por fugir do escopo deste post.

O código verifica se existe algum md5Mensagem na session, e se ele é igual ao md5 da mensagem enviada, se sim, ele informa que a mensagem já foi enviada, se não, o sistema tenta fazer o envio, se der certo ele salva o md5 na session, se não, ele apenas informa que não deu certo.

Bom, é isso, qualquer dúvida, postem comentários que responderemos.

Mensagens de Erro com Session em PHP (serialize)

Monday, February 11th, 2008

Pra quem pensa que a variável global SESSION é apenas para autenticação de usuários, aqui vai mais uma. O objetivo principal da SESSION, assim como dos COOKIES é enviar variáveis calculadas em uma página para outra página.

Irei apresentar aqui um sistema simples de mensagens de erro e confirmação com o uso da SESSION.

Primeiramente vou apresentar uma classe que eu usei para armazenar as mensagens:


<?
class Mensagem {
    public static $ERRO=1,$SUCESSO=2;

    private $mensagem;
    private $tipo;

    public function __construct($mensagem,$tipo){
        $this->mensagem = $mensagem;
        $this->tipo = $tipo;
    }

    public function getMensagem(){
        return $this->mensagem;
    }

    public function getTipo(){
        return $this->tipo;
    }

    public static function tipoToString($tipo){
        if($tipo == 1) return 'erro';
        else if($tipo == 2) return 'sucesso';
    }
}
?>

Pra quem já mexe com orientação a objetos, a classe acima é simples. Uma classe com 2 variáveis estáticas($ERRO e $SUCESSO) que seriam os tipos de mensagens, uso isso mais para definir o CSS que irá acompanhar a mensagem. Tem duas variáveis, uma para a mensagem em si, e outra para o tipo da mensagem, um construtor que define as variáveis, e funções para obter os valores das variáveis.

O uso é simples, vamos ver um caso abaixo:

Temos a página de formulário simplificada (form.php) da seguinte forma:


<?
if(isset($_SESSION['mensagens'])){
    $mensagens = unserialize($_SESSION['mensagens']);
    unset($_SESSION['mensagens']);
} else {
    $mensagens = array();
}

if(isset($_SESSION['pessoa'])){
    $pessoa = unserialize($_SESSION['pessoa']);
    unset($_SESSION['pessoa'];
} else {
    $pessoa = new Pessoa();
}

?>

<ul class="mensagens">
    <?= foreach($mensagens as $mensagem): ?>
    <li><p class="<?=Mensagem::tipoToString($mensagem->getTipo())?>"><?=$mensagem->getMensagem()?></p>  </li>
    <? endforeach; ?>
</ul>
<form action="insert.php" method="post">
    <input name="nome" value="<?=$pessoa->getNome()?>" type="text" />
    <input name="idade" value="<?=$pessoa->getIdade()?>" type="text" />
    <input type="submit" />
</form>

No código acima, criamos um formulário solicitando nome e idade. As primeiras linhas são código PHP, atente para a função unserialize, ela desserializa os dados que vieram da SESSION, visto que a mesma não suporta objetos. Pegamos da SESSION as mensagens, e apagamos da SESSION para que a mensagem só apareça uma vez. Fazemos o mesmo com um objeto do tipo pessoa, o qual armazena os dados que já foram enviados previamente, evitando que o usuário preencha o formulário novamente.

Abaixo vem uma lista, com todas as mensagens que estavam na SESSION. Atente para a função tipoToString, da classe mensagem, que eu criei apenas para definir o atributo class do parágrafo da mensagem.

Em seguida vem o formulário pegando todos os values do objeto pessoa que estava na SESSION.

Abixo teremos o script que irá processar este formulário (submit.php):


<?

$nome = $_POST['nome'];
$idade = $_POST['idade'];

$pessoa = new Pessoa();

if(!$nome) $mensagens[] = new Mensagem("O nome não foi informado",Mensagem::$ERRO);
else $pessoa->setNome($nome);

if(!is_numeric($idade)) $mensagens[] = new Mensagem("A idade deve ser um número!",Mensagem::$ERRO);
else $pessoa->setIdade($idade);

if(count($mensagens)){
    $_SESSION['mensagens'] = serialize($mensagens);
    $_SESSION['pessoa'] = serialize($pessoa);
    header("Location: form.php");
}

if(cadastra no banco){
    $mensagens[] = new Mensagem("Pessoa cadastrada com sucesso!",Mensagem::$SUCESSO);
} else {
    $mensagens[] = new Mensagem("Ocorreu um erro durante o cadastramento da pessoa!",Mensagem::$ERRO);
}

header("Location: form.php");

?>

No código acima, pegamos os dados do formulário através do POST e verificamos se os dados validam de acordo com algumas regras, caso contrário colocamos, em um array de mensagens, uma mensagem de erro. Depois de feita a validação, verificamos se existem mensagens de erro, caso positivo, serializamos as mensagens e a pessoa que possui alguns dados já cadastrados e colocamos na SESSION, fazendo o redirecionamento para o formulário, de forma que o usuário possa retificar seus erros.

Caso tudo ocorra dentro do normal, armazenamos uma mensagem de sucesso na SESSION, e redirecionamos para o formulário, para que o usuário efetue novo cadastro. Poderia redirecionar para a lista de cadastrados, ou qualquer outro lugar, contanto que o script tenha os códigos que lessem a mensagem de sucesso, mas para simplificar o meu post, eu criei apenas duas páginas.

Espero que isso ajude, e qualquer dúvida, comenta.