Nível: Básico - Intermediário.
Requerimentos Extras (bibliotecas): Nenhum.
===============-===============
Hello there!
Antes de mais nada, algumas explicações. Esse tutorial tem como base para o script, praticamente, JavaScript, mas porque PHP? Simples, estamos combinando as duas linguaguens para podermos trabalhar com dados em formulários (pode ir muito além), que se alteram dependendo de opções selecionadas, sem ter que atualizar a página, para fazer a requisição PHP novamente.
No mais, vamos ao que interessa.
===============-===============
Como é feito essa consulta?
Você se pergunta. É algo simples como uma query string. Na verdade, é uma pura query string. Quem já trabalhou com a integração de PHP + Flash, para fazer loadMovie()'s dinâmicos, etc, terá uma maior afinidade com esse tutorial.
Basicamente a consulta consiste em:
- Alterar algum valor;
- Passar esse valor como parâmetro para o PHP;
- Retornar o resultado que desejamos;
Beleza, vamos começar por onde?
Para todos terem o mesmo ponto de inicio, vamos seguir um exemplo do inicio ao fim. Nossa idéia é:
- Apresentar SubCategorias, dependendo da Categoria principal selecionada.
Simples? Sim, algumas consultas ao Banco de Dados, e está resolvido nosso problema.
Para começar, vamos a criação das Tabelas:
CREATE TABLE `categorias` ( `codigo` int(3) NOT NULL auto_increment, `nome` varchar(50) NOT NULL default '', PRIMARY KEY (`codigo`) );
CREATE TABLE `subcategoria` ( `codigo` int(3) NOT NULL auto_increment, `categoria` int(3) NOT NULL default '0', `nome` varchar(50) NOT NULL default '', PRIMARY KEY (`codigo`) );
Prontinho, vamos entender a estrutura:
Tabela Categoria:
- codigo: Campo AUTO_INCREMENT para armazenar o código de cada categoria.
- nome: Campo para adicionar o nome da categoria.
Tabela SubCategoria:
- codigo: Campo AUTO_INCREMENT para armazenar o código de cada subcategoria.
- categoria: Campo para referenciar à qual categoria cada categoria faz parte.
- nome: Campo para adicionar o nome da subcategoria.
Eita, já temos as tabelas, agora vamos colocar alguns valores para elas:
INSERT INTO `categorias` VALUES (1, 'Refrigerantes'); INSERT INTO `categorias` VALUES (2, 'Frutas'); INSERT INTO `categorias` VALUES (3, 'Carnes'); INSERT INTO `categorias` VALUES (4, 'Cervejas');
INSERT INTO `subcategoria` VALUES (1, 2, 'Maçã'); INSERT INTO `subcategoria` VALUES (2, 3, 'Alcatra'); INSERT INTO `subcategoria` VALUES (3, 1, 'Sprite'); INSERT INTO `subcategoria` VALUES (4, 1, 'Fanta'); INSERT INTO `subcategoria` VALUES (5, 2, 'Laranja'); INSERT INTO `subcategoria` VALUES (6, 4, 'Skol'); INSERT INTO `subcategoria` VALUES (7, 4, 'Bohemia'); INSERT INTO `subcategoria` VALUES (8, 1, 'Coca-Cola'); INSERT INTO `subcategoria` VALUES (9, 3, 'Coxão Mole'); INSERT INTO `subcategoria` VALUES (10, 2, 'Limão'); INSERT INTO `subcategoria` VALUES (11, 3, 'Picanha'); INSERT INTO `subcategoria` VALUES (12, 4, 'Brahma');
Certo, já temos algumas informações nas tabelas, vamos a parte que interessa agora.
===============-===============
Como apresentar as Categorias?
Para realizar a consulta das categorias, simplesmente, criamos nossa query selecionando os campos desejados:
SELECT * FROM categori<span style='color:green'>as ORDER BY nome ASC
Estamos selecionando todos os campos de todos os registros, ordenados pelo nome em ordem crescente (A-Z).
E como apresentar no form tudo isso?
Vamos criar nossa página então:
<select name="categoria"> <option></option> <?php $consulta = mysql_query("SELECT * FROM categorias ORDER BY nome ASC"); while( $row = mysql_fetch_assoc($consulta) ) { echo "<option value=\"{$row['codigo']}\">{$row['nome']}</option>\n"; } ?> </select>
Pronto, já temos um select com todas as categorias e um campo em branco no inicio, mas porque esse campo em branco? Pois nossa ação de XMLHttpRequest será no evento onchange, que é executa ao alterar o valor inicial.
Como ficaria nosso onchange?
<select name="categoria" onchange="pesquisar_dados( this.value )">
Para os conhecedores de JavaScript, chamamos uma função pesquisar_dados e passamos como um parâmetro, o value do select.
Uipi! Até agora, tudo beleza, e como montar o select para SubCategorias?!
Veja e surpreenda-se pequeno Gafanhoto.
<select name="subcategoria"></select>
Estava com preguiça, e vai ficar só assim nosso select.
Na verdade, os valores para ele, vai depender da Categoria selecionada, então, por inicio, não atribuimos nenhum valor à ele.
function pesquisar_dados()
Ahhh bom, achei que nunca iriamos chegar aqui. Veja o que seria essa função para receber o value da categoria selecionada:
function pesquisar_dados( valor ) { http.open("GET", "consultar.php?id=" + valor, true); http.onreadystatechange = handleHttpResponse; http.send(null); }
Vamos entender ela:
"Abrimos" a página consultar.php?id=X, digo "abrimos", pois na verdade, essa janela não será apresentada ao usuário, só será processada puxaremos o valor retornado. Logo após, aguardamos a resposta do processamento da página, e assim que finalizado, chamamos a nova função handleHttpResponse. Que processará nossa resposta.
function handleHttpResponse
Essa função tem a finalidade de "pegar" o resultado da página processada, e apresentar no seu defido lugar. Poderiamos jogar em um textarea, uma <div>, um <p>, ou até mesmo um alert.
function handleHttpResponse() { campo_select = document.forms[0].subcategoria; if (http.readyState == 4) { campo_select.options.length = 0; results = http.responseText.split(","); for( i = 0; i < results.length; i++ ) { string = results[i].split( "|" ); campo_select.options[i] = new Option( string[0], string[1] ); } } }
OOOOOOO LOOOOOOCOOOOOOOO MEEEEEUUUU!!! By Fausto Silva
Calma, calma, não corram. Vamos entender:
Antes de mais nada, definimos que campo será o receptor dos novos dados. Em seguida, verificamos se o estado do retorno é igual 4 (concluído), caso seja, definimos o campo receptor como 0 de length, ou seja, eliminamos todos as opções que existiam. Logo após, explodimos a resposta retornada pela nossa execução por ",", ou seja, cada SubCategoria, será separada por ",". Após isso, para cada índice retornado, explodimos ainda por "|", mas por que isso, você se pergunta, simples, nosso select não é somente 1 valor, mas 2, uma para a propriedade value e outro para a apresentação, primeiro a apresentação e em seguida o value. E por fim, adicionamos a opção ao nosso select.
OBA! Acabamos!!! Estamos vivos!!!!!
Calma jovem Anakin, o lado negro da força está por vir. Teríamos acabado se não tivessemos tantos navegadores por ai afora, e cada um com seu método de interpretação.
Como resolver? Simples, com mais uma função extra. Essa não precisará que nada seja alterado, afinal, é somente para identificação do Navegador e Suporte ao XMLHttpRequest.
function getHTTPObject() { var xmlhttp; /*@cc_on @if (@_jscript_version >= 5) try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { xmlhttp = false; } } @else xmlhttp = false; @end @*/ if (!xmlhttp && typeof XMLHttpRequest != 'undefined') { try { xmlhttp = new XMLHttpRequest(); } catch (e) { xmlhttp = false; } } return xmlhttp; } var http = getHTTPObject();
Somente uma passagem rápida por ela, definimos a nova função, e veja o detalhe, se você utilizar alguma IDE para o desenvolvimento dessas páginas, é bem provavel que identificará parte do código como um comentário, mas não é, não apague
Depois de fazer toda a verificação, a função é chamada e passada seu valor à variável global http.
Agora acabou?!
Técnicamente sim, mas como criar a página para retornar os resultados? Bom, agora entra nosso amigão PHP. Como vimos, cada registro precisa ser separado por ",", e a apresentação do value deve ser separado por "|".
<?php $con = mysql_connect("localhost", "usuario", "senha"); mysql_select_db("base_dados"); $categoria = addslashes($_GET["id"]); // pegamos o id passado pelo select $consulta = mysql_query("SELECT * FROM subcategoria WHERE categoria = '$categoria'"); // selecionamos todas as subcategorias que pertencem à categoria selecionada while( $row = mysql_fetch_assoc($consulta) ) { echo $row["nome"] . "|" . $row["codigo"] . ","; // apresentamos cada subcategoria dessa forma "NOME|CODIGO,NOME|CODIGO,NOME|CODIGO,...", exatamente da maneira que iremos tratar no JavaScript } ?>
Belezinha pessoas? Essa seria a página consultar.php, agora vejamos como ficaria a nossa página principal completa:
<?php $con = mysql_connect("localhost", "usuario", "senha"); mysql_select_db("base_dados"); ?> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <script language="javascript"> function pesquisar_dados( valor ) { http.open("GET", "consultar.php?id=" + valor, true); http.onreadystatechange = handleHttpResponse; http.send(null); } function handleHttpResponse() { campo_select = document.forms[0].subcategoria; if (http.readyState == 4) { campo_select.options.length = 0; results = http.responseText.split(","); for( i = 0; i < results.length; i++ ) { string = results[i].split( "|" ); campo_select.options[i] = new Option( string[0], string[1] ); } } } function getHTTPObject() { var xmlhttp; /*@cc_on @if (@_jscript_version >= 5) try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { xmlhttp = false; } } @else xmlhttp = false; @end @*/ if (!xmlhttp && typeof XMLHttpRequest != 'undefined') { try { xmlhttp = new XMLHttpRequest(); } catch (e) { xmlhttp = false; } } return xmlhttp; } var http = getHTTPObject(); </script> </head> <body> <form name="formulario" method="post" action=""> <p><select name="categoria" onchange="pesquisar_dados( this.value )"> <option></option> <?php $consulta = mysql_query("SELECT * FROM categorias ORDER BY nome ASC"); while( $row = mysql_fetch_assoc($consulta) ) { echo "<option value=\"{$row['codigo']}\">{$row['nome']}</option>\n"; } ?> </select></p> <p><select name="subcategoria"></select> </p> </form> </body> </html>
E se eu não quiser um select, mas sim, um texto?
Simples, teriamos que alterar somente a função para tratar o retorno:
function handleHttpResponse() { campo_text = document.forms[0].subcategoria; if (http.readyState == 4) { campo_text = http.responseText; } }
Dessa forma, o campo <textarea> ou quaisquer outros campos, ou tags, receberiam o valor retornado pela consulta, bastando somente tratar todos os textos na consulta.
===============-===============
Dedicatória
A todos vocês e principalmente a minha mamãe pelo Dia das Mães
Mesmo tendo a certeza que ela não vai ler esse tutorial, mas:
Mommy, I love you!