Back-End

15 set, 2008

Requisições assíncronas em PHP usando Ajax – Parte 01

Publicidade

O uso de métodos para incrementar a parte visual e funcional de site é muito usada e não é de hoje. Mensagens popup, caixas de diálogo e DIVs “mágicas” são exemplos de algumas das milhares de possibilidades neste meio.

Estes (e outros) recursos são largamente usados na internet, mesmo que de forma imperceptível, transformando o ato de navegar em uma experiência mais prazerosa e funcional.

O que permite aos desenvolvedores colocar todo seu potencial à prova são ferramentas client-side como o JavaScript e o CSS. Podemos dizer que todo o dinamismo e a beleza de um site faz uso dessas duas tecnologias, excluindo algumas como Flash e o próprio Java.

E com AJAX?

Na prática: quando você clica em um link ou submete (posta) um formulário, uma requisição é enviada ao servidor (HTTP) e uma resposta é esperada pelo navegador, que causa uma atualização (refresh) ao chegar. Vamos supor que você clique ali na opção “Artigos” no menu lateral. O que acontece após o clique? Seu navegador envia uma requisição ao servidor, que retorna o resultado desta e, para o navegador mostrar esse resultado, você nota que a página teve que carregar novamente.

Agora, imagine você preenchendo um formulário que possui duas caixas de combinação. Na primeira você seleciona seu estado e na segunda você tem que selecionar sua cidade. Para isso temos duas tabelas no banco de dados, a primeira guardando os estados e a segunda guardando as cidades (que fazem referência direta aos estados da primeira tabela).

Assim que você seleciona o estado, o site faz uma requisição para que apareça somente as cidades do estado selecionado. Como dito anteriormente, isso causará uma atualização no site inteiro, e é aí que entra o astro deste artigo! Ao invés de enviar uma requisição normal ao servidor, podemos usar o AJAX para enviar uma requisição assíncrona, ou seja, que não faça o site ter aquela atualização que, se não for bem trabalhada, faz você acabar perdendo os outros campos preenchidos do formulário.

Este é um pequeno exemplo das infinitas possibilidades do AJAX. Neste primeiro artigo vou mostrar como fazer esta requisição utilizando somente JavaScript, XML e PHP. Na parte 2 vou mostrar como funcionam duas APIs que facilitam este processo e no último um exemplo totalmente funcional de tudo o que foi abordado. Espero que gostem.

Criando a consulta ao banco

Como foi dito, as requisições trabalham com o formato XML, por isso nossa consulta deve responder com XML.

Como fazer?

Seguindo o mesmo exemplo da cidade e estado, vamos criar o seguinte banco:

  • Criando o banco de teste
CREATE DATABASE ajax; 
  • Com as seguintes tabelas:
  • Tabela que guarda os estados
CREATE TABLE estados (
id int(3) NOT NULL auto_increment,
nome varchar(100) NOT NULL default "",
uf varchar(2) NOT NULL default "",
PRIMARY KEY (id)

)

  • Tabela que guarda as cidades
CREATE TABLE cidades (
id int(3) NOT NULL auto_increment,
nome varchar(100) NOT NULL default "", 
estado varchar(2) NOT NULL default "",
PRIMARY KEY (id)
) 

Com o banco e as tabelas criadas, insira alguns valores para darmos continuidade.

Faremos o uso do PHP para consultar o banco e gerar o arquivo XML.

<?php
  /*
    * Arquivo consulta.php
  */
  // Abre uma conexão com o banco
  $conexao = mysql_connect("localhost", "root", "") OR DIE("Erro na conexão.");
  // Seleciona o banco a ser utilizado
  $banco = mysql_select_db("ajax") OR DIE("Erro ao selecionar o banco.");
  // Realiza a consulta
  $resultado = mysql_query( sprintf("SELECT id, nome FROM cidades WHERE estado=%d", $_REQUEST["estado"]) );
  // Gera o XML com o resultado desta pesquisa
  $XML = sprintf("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
  while ( $record = mysql_fetch_array($resultado, MYSQL_ASSOC) ) {
    $XML .= sprintf("<cidade>\n");
    $XML .= sprintf("<id>%s</id>\n", $record[´id´]);
    $XML .= sprintf("<nome>%s</nome>\n", $record[´nome´]);
  }

  // HEADER do arquivo XML
  Header("Content-type: application/xml; charset=iso-8859-1");
  // Mostra os dados
  printf("<cidades>\n%s</cidades>\n", $XML);
?> 

Observe que foi usado o método $_REQUEST["estado"] para que o estado possa ser passado tanto por POST quanto por GET, isso vai de cada um.

Em posse da pesquisa, vamos ver como chamar este arquivo via JavaScript.

Segunda parte: Requisição JavaScript

A requisição

A requisição feita é pelo JavaScript usando um objeto milagroso, o XMLHttpRequest(). Mas como ele faz tal requisição?

Simples:

// Função que recupera os dados da pesquisafunction catchDados(valor) {
function catchDados(valor) {
  // Instancia o objeto
  ajax = new XMLHttpRequest();
  // Recupera o combo-box ESTADOS
  estados = document.getElementById(´estados´);
  // Recupera o combo-box CIDADES
  cidades = document.getElementById(´cidades´);
  if (ajax) {
    // Limpa o combo-box CIDADES
    cidades.options.length = 1;

    // Faz a requisição
    ajax.open("POST", "consulta.php", true);
    ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

    // Vamos processar os estados da requisição
    ajax.onreadystatechange = function() {
      // Carregando...
      if (ajax.readyState == 1) {
        cidades.innerHTML = "Carregando...";   
      }
      // Ao receber a resposta
      if (ajax.readyState == 4 ) {
        if (ajax.responseXML) {
          montaCombo(ajax.responseXML);
        } else {
          cidades.innerHTML = "Selecione o estado.";
        }
      }
    }
    // Envia os parâmetros
    var params = "estado="+valor;
    ajax.send(params);
} 

A função descrita acima faz a requisição e trata seus status (carregando e carregado) e, quando recebido o resultado, passa para a função ´montaCombo´ (descrita a seguir) que insere os dados do arquivo XML no combo.

function montaCombo(XML){
  // Array com os dados das cidades
  var CIDADES = XML.getElementsByTagName("cidade");
  // Recupera o combo-box CIDADES
  cidades = document.getElementById(´cidades´);

  // Verifica se a consulta retornou alguma coisa
  if (CIDADES.length > 0) {
    // Lemos todo o arquivo XML
    for(var i = 0 ; i < XML.length ; i++) {
      item = XML[i];
      ID = item.getElementsByTagName("id")[0].firstChild.nodeValue;
      NOME = item.getElementsByTagName("nome")[0].firstChild.nodeValue;

      cidades.innerHTML = "Escolha...";
      // Aqui e DOM, assunto para um outro artigo
      // Cria os dados dentro do combo
      opt = document.createElement("option");
      opt.value = id;
      opt.text  = nome;
      cidades.options.add(opt);
    }
  } else {
    // caso o XML retorne em branco
    cidades.innerHTML = "Escolha o estado.";
  }
} 

Espero que não esteja muito confuso, pois a base é um tanto trabalhosa mesmo. Como se pode notar, há uma parte em que foi usada a expressão DOM. DOM é uma técnica para manipular objetos HTML em tempo real, assunto para um próximo artigo. O que é feito ali usando DOM é criar os ´options´ do combo-box com as opções retornadas pelo XML.

Próximo passo, nosso fomulário HTML.

Última parte: Formulário completo

Depois de termos entendido todas as funções, tanto PHP quanto JavaScript, vamos ao formulário principal do nosso teste.

<html>
   <head>
      <title>PHP + AJAX</title>
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
   </head>
   
   <body>
      <h1>AJAX + PHP</h1>
  Recuperando dados sem refresh, usando AJAX.
      <br><br>
  
  <form>
     Estado:
     <select name="estados" id="estados" onChange="catchDados(this.value);">
        <option value="">Escolha...</option>
    <?php
                      /*
                        * Carregando os estados
                      */
                      $conexao = mysql_connect("localhost", "root", "") OR DIE("Erro na conexão.");
                      $banco = mysql_select_db("ajax");
                      $resultado = mysql_query( sprintf("SELECT id, nome FROM estados ORDER BY nome ASC") );
                      while ($record = mysql_fetch_array($resultado, MYSQL_ASSOC)) {
                        printf("<option value=\"%s\">%s</option>\n", $record[´id´], $record[´nome´]);
                      }
                    ?>
        </select>
         <br>
        Cidade:
        <select name="cidades">
            <option id="" value="">Escolha o estado...</option>
        </select>
     </form>
   </body>
</html> 

Pronto, espero vocês na próxima parte deste artigo, onde vamos facilitar estes códigos usando APIs.

Abraços.

Artigo originalmente publicado em VivaoLinux.com.br