Como usar o Form Validation com uma função de Callback

A biblioteca Form Validation do CodeIgniter é muito útil e simples de usar quando queremos validar no lado do servidor os campos de um formulário HTML.

O uso padrão que ela oferece já é de grande valia, porém, esta biblioteca tem uma funcionalidade muito interessante que nos permite chamar uma terceira função para verificar um campo.

Digamos que você não quer validar somente se um campo está vazio ou não, mas na verdade, precisa analisar o conteúdo do que foi postado e baseado nisso, mandar uma mensagem personalizada ao usuário.

Vamos tomar como exemplo o seguinte caso:

Você disponibiliza um formulário comum ao usuário porém com um campo de envio de arquivos que aceita somente imagens de no máximo 2MB.

Todos os campos são de preenchimento obrigatório, exceto o do arquivo.

Porém, caso o usuário decida enviar um arquivo, você precisará verificar se o que o usuário enviou é uma imagem e também o seu tamanho.

Ou seja, nas suas regras de validação, você não poderá colocar esta campo como obrigatório.

A solução é você indicar na regra de validação deste campo uma função de callback, ou seja, o CodeIgniter vai chamar um método que terá como função analisar o conteúdo do campo e a partir disto devolver uma resposta apropriada.

No post de hoje eu não vou mostrar uma aplicação completa, somente o trecho de código responsável por fazer tudo isto funcionar.

Digamos que você tem um controller com um método chamado store() que é responsável por receber os dados vindos do formulário.

Dentro deste médodo, existem as seguintes regras de validação, veja abaixo:

No código acima a novidade é o que consta na regra de validação do campo chamado userfile.

Repare que em “rules” eu chamo um método chamado verifica_tamanho_anexo que está dentro do próprio controller. Para você chamar um método basta você acrescentar o prefixo “callback_“, que quando a validação atingir este ponto, seu método será chamado.

O restante do código é o padrão da biblioteca form validation, ou seja, se o retorno da execução do método run() do form validation for igual a FALSE, indica que o formulário não foi validado, então chamo a view novamente, caso contrário, eu continuo e escrevo o restante do código que irá salvar os dados no banco, que não está sendo mostrado aqui.

Veja abaixo agora o método verifica_tamanho_anexo:

Repare que nesta função eu uso uma outra biblioteca do CodeIgniter responsável pelo upload de arquivos chamada File Upload.

Todo o conteúdo de um envio de arquivo através de um formulário fica dentro da variável super global chamada $_FILES e ali dentro há um índice chamado ‘userfile‘ que corresponde ao nome do campo no formulário.

Este índice também é uma array e dentro dele existe um outro índice chamado ‘name‘ que me retorna o nome do arquivo enviado.

E é aqui que eu verifico se um arquivo foi ou não postado simplesmente através da função empty() do PHP.

Caso nada tenha sido postado, a verificação do IF irá retornar TRUE, e então eu saio da função com um simples return TRUE, que indicará ao Form Validation que o formulário poderá ser postado, já que o campo de anexo não é obrigatório.

Caso algum arquivo tenha sido enviado, então eu passo para a verificação do tamanho e formato do arquivo.

A biblioteca File Upload do CodeIgniter é bem simples de entender. Aqui basicamente eu configuro os parâmetros da biblioteca e também os formatos de arquivo permitido e seu tamanho máximo em kilobytes.

Caso o arquivo passe no teste de verificação eu simplesmente dou um return TRUE e saio da função, indicando ao Form Validation que o teste passou e que nesse caso há um arquivo em anexo.

Caso o arquivo não tenha passado no teste você poderá recuperar o erro através do método display_errors() da biblioteca Upload.

Neste caso o que eu faço é atribuir este erro ao campo de arquivo, e eu faço isso através desta linha:

Aqui eu consigo vincular o tipo de erro ao campo que está sendo verificado através da passagem do nome da função como parâmetro, neste caso somente: verifica_tamanho_anexo.

Após isso eu dou um return FALSE que vai indicar ao Form Validation que a validação não foi bem sucedida, e assim a view é recarregada com a mensagem de erro em questão.

Lembre-se que as mensagens de erro por padrão estão em Inglês. Você pode baixar um pacote de tradução do CodeIgniter lá no github ou então traduzir por conta própria este arquivo: system/language/english/form_valdiation_lang.php.

E desta maneira você pode criar agora suas próprias funções de validação que trabalharão em conjunto com o Form Validation, estendendo, assim, sua funcionalidade.

Abraços

Fábio

Fábio S. Reszko

Sou Programador PHP desde 2006 e eu acredito sinceramente que programar usando um Framework PHP é a solução para os problemas de códigos desorganizados, difíceis de entender e de dar manutenção no futuro. Se você também acredita nisto, então fique à vontade em explorar meu blog.

  • Parabens amigo!

  • Alguém já conseguiu fazer upload múltiplo no CI? Tô apanhando para fazer funcionar… Se alguém puder ajudar..

  • Luis Eduardo Lima

    alguém poderia me ajuda neste erro, faço a validação dos campos de autenticação, se usuário não exista ele da a mensagem de boa, mas quando coloco o usuário e a senha correta ele não encontra a pagina panel que é minha pagina de menu

  • douglas88

    No meu caso fica aparecendo este erro, e não funciona:
    “Não existe uma mensagem de erro para o campo com o nome user_email.(check_email)”;

    OBS: Check_email é a minha função callback …

  • douglas88

    A solução que achei foi esta, em um fórum:

    Solução:

    1. Criar MY_Form_validation.php arquivo na pasta de bibliotecas e cole o seguinte código nele.

    if (!defined(‘BASEPATH’)) exit(‘No direct script access allowed’);
    class MY_Form_validation extends CI_Form_validation
    {

    function run($module = ”, $group = ”)
    {
    (is_object($module)) AND $this->CI = &$module;
    return parent::run($group);
    }
    }

    E mudar if ($this->form_validation->run() == FALSE) para if ($this->form_validation->run($this) == FALSE) isso é tudo pessoal ..

  • douglas88
  • douglas88

    Boa noite pessoal, quando vou tentar validar alguns campos que NÃO estejam dentro de $_POST, eu devo usar o método $this->form_validation_>set_data($data); , porém , mesmo com o meu campo preenchido, quando vou validar um campo “required”, a biblioteca de validação diz que os campos estão vazios.

    Depois de muito bater cabeça, encontrei uma biblioteca de validação (Validation.php), no github , que resolveu o meu problema.

    Segue o link : https://github.com/lumoz/codeigniter-form-validation

    Valeu.

  • O ruim de usar o set_data é que você precisa informar todos os campos do formulário novamente, mesmo se precisa alteraras informações de somente um deles.

  • douglas88

    Também, mas nesse meu caso eu não estou usando a global $_POST, somente quero validar uma variável que estou passando, e mesmo assim o CI diz que ela está vazia, quando válido usando o “require” …

  • roberto joao rosa jr

    Olá, tem como disponibilizar o funcionamento destas dicas em algum tipo de teste online e/ou codigo pra tentar descobrir onde estamos errando? Não estou conseguindo mostrar os erros de validação na tela. Obrigado pelas dicas!

  • Olá Roberto.

    É complicado fazer isto pois se eu colocasse um código aqui, ele estaria funcionando. Veja se no seu index.php a constante ENVIRONMENT está setada para development, assim os erros aparecem.

    Você pode consultar também o log de erros do apache. Lá tem muita coisa interessante.

    Valeu.

  • Rônald A. S

    Olá Fabio.

    Como eu faço para usar as validação nativas do form_validation e conjunto com uma validação própria:

    Algo do tipo assim:

    array(
    ‘field’ => ‘userfile’,
    ‘label’ => ‘Anexar Imagem’,
    ‘rules’ => ‘required’, ‘min_length[14]’, ‘is_unique[tbl_userfile.name]’, ‘callback_verifica_tamanho_anexo’
    ),

  • Olá Ronald.

    Na verdade o post se trata exatamente disto. Como usar as funções nativas do form_validation junto com uma validação própria, no caso, verifica_tamanho_anexo.

    Abraços
    Fabio