goncin@wordpress.com:~$ _

Linux, programação e toda sorte de nerdices

Gerador de formulários HTML em PHP orientado a objetos (parte 2)

Se você chegou aqui diretamente, recomendo que você dê uma olhada na parte 1, sob pena de não entender nada 😛 …

Aqui estou eu novamente, continuando meu brainstorm a respeito de um gerador de formulários HTML implementado em PHP orientado a objetos. Como eu havia dito, ainda havia controles a implementar, e então aqui vai mais um, o <select> (drop down):

class GSelect extends GFormControl {

    private $_items = array();
    private $_selectedValue = null;

    public function  __construct($id, $label = '', $attributes = array(), $items = array(), $selectedValue = null) {
      $this->setId($id);
      $this->setLabel($label);
      $this->setAttributes($attributes);
      $this->setItems($items);
      $this->setSelectedValue($selectedValue);
    }

    protected function getOpenTag() {
      return '<select';
    }

    protected function getCloseTag() {
      return "\t</select>";
    }

    public function setItems($items) {
      if (is_array($items)) $this->_items = $items;
      return $this;
    }

    public function getItems() {
      return $this->_items;
    }

    public function setSelectedValue($value) {
      $this->_selectedValue = $value;
      return $this;
    }

    public function getSelectedValue() {
      return $this->_selectedValue;
    }

    protected function renderField() {
      $html = $this->getOpenTag() . " id='{$this->getId()}' ";
      $html .= $this->renderFieldAttributes() . ">\n";

      $items = $this->getItems();

      foreach($items as $value => $text) {
        $html .= "\t\t<option value='{$value}'";
        if ($value === $this->getSelectedValue())
           $html .= " selected='selected'";
        $html .= ">{$text}</option>\n";
      }

      $html .= $this->getCloseTag();

      return $html;
    }

  }

Este controle deu um pouco mais de trabalho para codificar porque, ao contrário dos anteriores, ele não é baseado na tag <input>. Basicamente, foi necessário fazer isso:

  • implementar métodos para configurar e retornar os itens da lista de seleção (setItems() e getItems());
  • implementar para configurar e retornar o valor que já virá selecionado na lista (setSelectedValue() e getSelectedValue());
  • sobrescrever método renderField(), a fim de refletir as particularidades desse controle; e
  • sobrescrever o construtor para que este aceitasse dois novos parâmetros, $items e $selectedValue, de forma que o controle pudesse ser totalmente configurado no momento de sua criação.

Por fim, ficou faltando escrever o controle que represente o próprio formulário (<form>). Isso foi feito facilmente, estendendo também o GForm a partir de GFormControl.

  class GForm extends GFormControl {

    private $_controls = array();

    protected function getOpenTag() {
      return '<form';
    }

    protected function getCloseTag() {
      return '</form>';
    }

    public function addControl($control) {
      if ($control instanceof GFormControl) $this->_controls[] = $control;
      return $this;
    }

    protected function getControls() {
      return $this->_controls;
    }

    protected function renderField() {
      $html = $this->getOpenTag() . " id='{$this->getId()}' action='{$this->getLabel()}' ";
      $html .= $this->renderFieldAttributes() . ">\n";

      $controls = $this->getControls();

      foreach($controls as $ctl)
        $html .= "{$ctl->render()}\n";

      $html .= $this->getCloseTag();

      return $html;

    }

    public function render() {
      return $this->renderField();
    }

  }

O grande diferencial do GForm em relação aos controles anteriormente desenvolvidos é sua capacidade de ter controles filhos, cujo gerenciamento básico é feito pelos métodos addControl() e getControls(). Assim, quando for chamado o método render() do formulário, este fará a chamada ao método render() de cada um de seus filhos, poupando-nos linhas de código. E, por tocar no assunto de economia de codificação, reparem que o método addControl() retorna a instância do objeto ($this), permitindo-nos montar o formulário mediante chamadas de métodos encadeados. Vejam só:

  $opcoes = array (
    0 => '(Selecione)',
    1 => 'Aluno',
    2 => 'Professor',
    3 => 'Administrativo'
  );

  $form = new GForm('form1', 'proc_login.php');

  echo $form
    ->addControl(new GTextBox('usuario', 'Usuário:', array('maxlength'=>50, 'size'=>15)))
    ->addControl(new GPassword('senha', 'Senha:', array('maxlength'=>50, 'size'=>15)))
    ->addControl(new GSelect('tipo_acesso', 'Tipo de Acesso:', null, $opcoes, 2))
    ->addControl(new GCheckBox('guardar_info', 'Guardar informações?'))
    ->addControl(new GSubmit('enviar', 'Enviar'))
    ->render();

O segundo parâmetro do construtor, que nos outros controles é o texto descritivo (label), no caso do GForm serve para especificar o valor do atributo action. As linhas 10 a 16 constituem uma única instrução, encadeando métodos. O <select> gerado vem com a opção de valor 2 pré-selecionada (último parâmetro do construtor do GSelect).

Eis o código fonte HTML gerado:

<form id='form1' action='proc_login.php' >
<div>
	<label for='usuario'>Usuário:</label><br />
	<input type='text' id='usuario' maxlength='50' size='15' />
</div>

<div>
	<label for='senha'>Senha:</label><br />
	<input type='password' id='senha' maxlength='50' size='15' />
</div>

<div>
	<label for='tipo_acesso'>Tipo de Acesso:</label><br />
	<select id='tipo_acesso' >
		<option value='0'>(Selecione)</option>
		<option value='1'>Aluno</option>
		<option value='2' selected='selected'>Professor</option>
		<option value='3'>Administrativo</option>
	</select>
</div>

<div>
	<label for='guardar_info'>Guardar informações?</label><br />
	<input type='checkbox' id='guardar_info' />
</div>

<div>
	<input type='submit' id='enviar' value='Enviar' />
</div>

</form>
Aparência do formulário HTML gerado pelo código PHP

Aparência do formulário HTML gerado pelo código PHP

Mais uma vez, devo agradecê-lo por me acompanhar na leitura deste loooooongo e super-hiper-mega-técnico post. Espero que tenha valido a pena, que você tenha compreendido o que eu quis demonstrar (conceitos de programação orientada a objetos), e que tenhamos, eu e você, aprendido coisas novas. 😀

Anúncios

19 Respostas para “Gerador de formulários HTML em PHP orientado a objetos (parte 2)

  1. Luiz Morais Junior 20/08/2010 às 15\0328

    Parabéns, muito bom seu código, me ajudou muito. mas só uma dúvida: esta dando um erro: Warning: Invalid argument supplied for foreach() in C:\…\GFormControl.class.php on line 109. o que é isso?

    • goncin 20/08/2010 às 16\0400

      Luiz,

      Os códigos apresentados não chegam à linha 109. Como você conseguiu esse erro?

      • demoraisjunior 20/08/2010 às 17\0529

        rsrsrs é que eu fui lendo e comentando algumas coisas, foi mal ae … ta dando erro na classe GFormControl nesta parte ….


        // Renderiza os atributos do campo de formulário
        protected function renderFieldAttributes()
        {
        $html = '';

        foreach($this->getAttributes() as $attr => $value)
        $html .= "{$attr}='{$value}' ";

        return $html;
        }

  2. goncin 20/08/2010 às 21\0957

    Luiz,

    Tente ver o que o método getAttributes() está retornando antes do foreach. Certamente você encontrará aí a chave da solução. 😉

  3. Renato Tavares 20/08/2010 às 22\1030

    PHP orientado a objetos para mim é grego =(

    • goncin 20/08/2010 às 22\1035

      Então o jeito é aprender grego logo. E nem é tão difícil assim… 😉

      • Marcelo Bezerra 24/05/2013 às 11\1145

        kkk muito bom.
        Caro Renato não programava nada em Orientação a objetos até fevereiro desse ano.
        HJ. não consigo mais fazer nada se não for em O.O.

  4. Leandro 17/02/2011 às 08\0844

    Parabéns! Essa classe vai me poupar muito trabalho na geração de formulários (sim, utilizarei-a em meus projetos…hahaha)

  5. Jorge 12/04/2011 às 14\0242

    Warning: Invalid argument supplied for foreach() in F:\wamp\www\secretaria saude\REDOME\sistema\include\class\forms.class.php on line 97

    Como soluciono o erro referente a esta função:

    // Renderiza os atributos do campo de formulário
    protected function renderFieldAttributes()
    {
    $html = ”;

    foreach($this->getAttributes() as $attr => $value)
    $html .= “{$attr}='{$value}’ “;

    return $html;
    }

  6. Jorge 12/04/2011 às 15\0329

    O erro pode estar vinculado ao array !?
    Pois quando comento a linha que gera o campo select não dá erro 🙂

    $opcoes = array (
    0 => ‘(Selecione)’,
    1 => ‘Aluno’,
    2 => ‘Professor’,
    3 => ‘Administrativo’
    );

    $form = new GForm(‘FrmLogin’, ‘proc_login.php’);

    echo $form
    ->addControl(new GTextBox(‘usuario’, ‘Usuário:’, array(‘maxlength’=>50, ‘size’=>15)))
    ->addControl(new GPassword(‘senha’, ‘Senha:’, array(‘maxlength’=>50, ‘size’=>15)))
    /*->addControl(new GSelect(‘tipo_acesso’, ‘Tipo de Acesso:’, null, $opcoes, 2))*/
    ->addControl(new GCheckBox(‘guardar_info’, ‘Guardar informações?’))
    ->addControl(new GSubmit(‘enviar’, ‘Enviar’))
    ->render();

    Grato pela atenção.

    • goncin 12/04/2011 às 15\0334

      Jorge,

      Realmente, o código do método

      renderFieldAttributes()

      tinha um bugzinho. Experimente esta versão:

          protected function renderFieldAttributes() {
            $html = '';
      
            if ($attrs = $this->getAttributes())
              foreach($attrs as $attr => $value)
                $html .= "{$attr}='{$value}' ";
      
            return $html;
          }
      
  7. Jorge 12/04/2011 às 16\0405

    Solucionado. (Desculpa o spam)
    Na linha
    /*->addControl(new GSelect(‘tipo_acesso’, ‘Tipo de Acesso:’, null, $opcoes, 2))*/
    Se informar o array com qualquer atributo ao inves de inserir “null” não retorna o erro;
    .

  8. Pretenso POOta desenvolvedor 30/05/2012 às 21\0919

    Kra, adorei sua abordagem.
    Só acho q o container não deveria herdar na classe origem dos controles.
    Outra coisa: podemos colocar o id do controle ($control->getId();) como chave do array, para podermos chamá-lo posteriormente e até acessar seu value, por exemplo no input text.
    A partir da sua idéia, estou pensando em fazer uma classe, simulando uma enumeração, com constantes relativas a atributos css.
    Penso também em desmembrar os atributos das classes.
    Kra… vc abriu os meus olhos pra essa questão.
    Muito, mas, muito obrigado msm!!!
    Deus te abençoe.

  9. Leonardo Fabra Gomez 09/08/2012 às 08\0810

    Blza? Por acaso você consegue disponibilizar a classe completa em um arquivo zip? Se poder enviar por email eu agradeço. Parabéns, excelente classe!

  10. Rafael 13/05/2013 às 15\0304

    Muito bom, no livro php programando com Orientação a Objetos, o autor coloca exemplos de criação de formulários também com OO, mas na minha visão é muito interessante para a pessoa estudar e aprender OO, já que muitas pessoas possuem dificuldade de aprender esse paradigma, mas para colocar em um projeto acaba gerando mais trabalho para o servidor ao invés de deixar o html ser apenas processado pelo browser, dessa forma será códigos php trabalhando dentro do servidor para gerar html, depois mais o navegador que vai ler o html gerado.

    Por um outro lado, pode ser interessante para criar plugins do WordPress.

  11. Luiz 02/06/2014 às 20\0851

    Pra q isso? vc tem q colocar php no html e nao html no php

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: