Validando um elemento individual em um formulário Drupal

Alô pessoal! Hoje vou abordar um assunto que já vi várias pessoas com alguma dificuldade do tipo: Validação de itens nos formulários, que é diferente de validar um formulário inteiro. Não será uma abordagem a fundo, mas tenho certeza que os exemplos citados aqui serão de grande utilidade para quem está fazendo seus próprios módulos.

A principal diferença aqui, é que não vamos usar funções complexas que são usadas para validar de forma ampla. Vamos pegar coisas mais simples, que é o caso de quando precisamos validar um único campo. Em teoria, nós não precisamos de funções de forma ampla. Podemos adicionar um manipulador em cada item de formulário usando o elemento #element_validate. Assim podemos definir nossas próprias funções de validação dos elementos. Também, para validar números/inteiros, podemos usar manipuladores de validação pré-definidos com apenas uma linha de código. Maravilha!

Exemplo 1: validando cores

Vamos supor que você tenha um cliente que só gosta das cores azul, amarelo, rosa e roxo e ele não quer um campo dropdown com apenas essas cores. Em vez disso, esse cliente pede para que o formulário seja validado de forma que, se um usuário digita outra coisa que não for essas cores, eles vão receber um erro. Beleza! Cada um com seu gosto.

Validação padrão de forma ampla

Vamos dar uma olhada em como deve ser a validação de um formulário simples com uma função de forma ampla.

/**
 * Implements hook_form().
 */
function mymodule_form($form, &$form_state) {
  $form['colour'] = array(
    '#type' => 'textfield',
    '#title' => t('colour'),
    '#size' => 4,
    '#required' => TRUE,
    '#default_value' => variable_get('colour', 'blue'),
  );
 
  return system_settings_form($form);
}
 
/**
 * Implements hook_validate().
 */
function mymodule_form_validate($form, &$form_state) {
  $allowed = array('blue', 'yellow', 'pink', 'purple');
  if (!in_array($form_state['values']['colour'], $allowed)) {
    form_set_error('colour', t('You must enter a valid colour.'));
  }
}

Aqui estamos verificando que os usuários enviem somente azul, amarelo, rosa ou roxo no campo de cores. Se eles inserirem qualquer outra coisa, verão um erro e não conseguirão submeter o formulário. O primeiro argumento para form_set_error() é o elemento do formulário que define o erro relacionado, que neste caso, é a cor. Ao verificar o erro na submissão do formulário, o campo cor será destacado para que o usuário saiba que este campo tem uma informação incorreta.

Função de validação para um elemento individual

Para validar um elemento individual, nós precisamos adicionar um #element_validade ao elemento do formulário, com a função específica de validação do elemento. Essa função deve ser passada através de $element e $form_state. Usando o exemplo da mesma forma que usamos acima, definimos uma função de validação para o elemento de cor, ao invés de usar para o formulário todo.

Segue a função de validação para o elemento:

function mymodule_colour_validate($element, $form_state) {
  $allowed = array('blue', 'yellow', 'pink', 'purple');
  if (!in_array($form_state['values']['colour'], $allowed)) {
    form_error($element, t('You must enter a valid colour.'));
  }
}

Uma das principais diferenças desta função entre a função larga de validação, é que no exemplo anterior foi usado form_error() ao invés de form_set_error(). O primeiro argumento para o form_set_error() é o nome do elemento para definir o erro relacionado. Com funções de validação do elemento, já temos o elemento e por isso, não precisamos passar esse parâmetro com um argumento. Sabendo disso, usamos o form_error().

Para chamar essa função no elemento do formulário, precisamos adicionar o seguinte:

'#element_validate' => array('myform_colour_validate'),

O elemento no formulário ficará assim:

$form['colour'] = array(    '#type' => 'textfield',
    '#title' => t('colour'),
    '#required' => TRUE,
    '#size' => 4,
    '#default_value' => variable_get('colour', 0),
    '#element_validate' => array('mymodule_colour_validate'),
  );

Isso pode parecer mais difícil do que usando apenas uma função de validação de formulário. No entanto, é bom pensar que estamos validando vários elementos de formulário. Certamente é mais fácil e fica mais limpo para separá-los, ao invés de ter uma função de validação grande. Código limpo é muito mais fácil de manter. Dessa forma, nós também podemos reutilizar a função de validação do mesmo elemento em vários formulários. O reuso de código é sempre uma coisa boa! :)

Exemplo 2: validando números

Para este exemplo, vamos colocar como critério, que o usuário poderá informar somente números em um campo "número".

Validação padrão de forma ampla

Um formulário simples com um campo "número" e uma função de validação ampla:

/**
 * Implements hook_form().
 */
function mymodule_form($form, &$form_state) {
  $form['number'] = array(
    '#type' => 'textfield',
    '#title' => t('My field'),
    '#required' => TRUE,
    '#size' => 4,
    '#default_value' => variable_get('my_field', 0),
  );
  return system_settings_form($form);
}
 
/** 
 * Implements hook_validate().
 */
function mymodule_form_validate($form, &$form_state) {
  if (!is_numeric($form_state['values']['number'])) {
    form_set_error('number', t('Field must be Numeric'));
  }
}

Estamos verificando que os usuários insiram um número no campo de "número", passando-o através do campo PHP is_numeric. Se não é um número, o usuário receberá uma mensagem de erro e o campo "número" será destacado.

Função de validação para um elemento individual

Callbacks de validação do elemento entrarão aqui, quando estamos para um campo "número", pois podemos usar um manipulador de pré-definido. Com o manipulador pré-definido, nós não precisamos adicionar a função de validação, pois ela já existe. No exemplo anterior, verificamos que o campo número era de fato um número passando através da função de validação is_numeric, na forma ampla.

O Drupal já tem definido um manipulador que valida os dados que são um número, chamado element_validate_number().

Dessa forma, a única coisa que precisamos acrescentar ao nosso elemento é o seguinte:

'#element_validate' => array('element_validate_number'),

O código no formulário vai ficar assim:

$form['number'] = array(
    '#type' => 'textfield',
    '#title' => t('My field'),
    '#required' => TRUE,
    '#size' => 4,
    '#default_value' => variable_get('my_field', 0),
    '#element_validate' => array('element_validate_number'),
  );

Sendo assim, pudemos ver nesse último exemplo que a validação foi adicionada com apenas uma linha de código! Formidável! :)

Nós também podemos usar element_validade_integer() e element_validate_integer_positive() como manipuladores de validação.

É isso! Neste artigo nós vimos três formas de validar dados em um formulário:

  • Função de validação de forma ampla
  • Função de validação de um elemento com uma função personalizada
  • Função de validação de um elemento através de um manipulador pré-definido

 

Certamente, em algum projeto, você vai se deparar com situações onde o uso de validar um elemento será uma coisa melhor a se fazer, ao invés de usar uma função de validação de formulário de forma ampla. Usando o validador de elemento nos leva a um código mais limpo e nos dá mais possibilidade de reutilização de código. Código mais limpo é sempre uma coisa boa e deixa muito mais fácil para você e outros desenvolvedores de manter.

 

Este post é uma tradução livre adaptada do Blair Wadman.