And After - Design e Tecnologia por Sua Conta!
OD

Selects aninhados - fazendo uma busca

Média

Por Chris Benseler em Internet, Programação,

Como fazer uma busca aninhada por selects, usando PHP e MySQL

Provavelmente já existem muitos tutoriais na net de como fazer uma busca por selects aninhados usando (a metodologia) ajax. Mas, como na web sempre tem gente nova chegando, e novas abordagens são sempre bem-vindas, vou mostrar como fazer uma dessas buscas de uma forma bem simples.
O que é necessário: um banco MYSQL rodando, PHP (versão 4 já da conta) e a biblioteca javascript prototype.
Tendo os ingredientes à mão, vamos criar um banco de dados com duas tabelas:
bandas: campos ID e NOME
discos: campos ID, ID_BANDA, NOME

A idéia é que a tabela bandas liste várias bandas (sendo ID chave primária), e a tabela discos vai guardar uma lista de discos referentes às bandas inseridas na outra tabela (usando ID_BANDA para referenciar a qual a banda o disco pertence).
Segue um dump do banco:

 
CREATE TABLE `bandas` (

  `id` int(11) NOT NULL auto_increment,

  `nome` varchar(128) NOT NULL,

  PRIMARY KEY  (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;



-- 

-- Extraindo dados da tabela `bandas`

-- 



INSERT INTO `bandas` VALUES (1, ´Iron Maiden´);

INSERT INTO `bandas` VALUES (2, ´Metallica´);

INSERT INTO `bandas` VALUES (3, ´Sepultura´);



-- --------------------------------------------------------



-- 

-- Estrutura da tabela `discos`

-- 



CREATE TABLE `discos` (

  `id` int(11) NOT NULL auto_increment,

  `id_banda` int(11) NOT NULL,

  `nome` varchar(128) NOT NULL,

  PRIMARY KEY  (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;



-- 

-- Extraindo dados da tabela `discos`

-- 



INSERT INTO `discos` VALUES (1, 1, ´Fear of the Dark´);

INSERT INTO `discos` VALUES (2, 1, ´The Number of the Beast´);

INSERT INTO `discos` VALUES (3, 2, ´Load´);

INSERT INTO `discos` VALUES (4, 2, ´Master of Puppets´);

INSERT INTO `discos` VALUES (5, 3, ´Chaos AD´);

INSERT INTO `discos` VALUES (6, 3, ´Arise´);



Tendo feito isso, monta-se uma página com um formulário que possui dois selects. Através de uma consulta SQL feita pelo PHP ,todos os registros da tabela bandas são retornados e o primeiro select é populado, colocando o value de cada option igual ao id da banda (ele será usado para fazer a consulta SQL na tabela discos de uma banda específica).
No onchange desse select, se chama uma função javascript:
- ela vai fazer uma requisição utilizando o objeto Ajax da (biblioteca) prototype, a uma página php chamada discos.php
- discos.php consulta a tabela discos e procura os discos de uma banda específica, retornando uma string no formato registro1|registro2|registro3...
- no retorno da função, por javascript é feito um split na string retornada e, com isso, recupera-se num vetor a lista de discos. Com isso, só é necessário apagar os ítens anteriores da lista, percorrer o vetor gerado pelo split e criar para cada item dessa lista uma option e adicioná-la (appendChild()) ao select.

Segue o código da página principal:

 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

<title>Exemplo de select aninhado</title>

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.2/prototype.js"></script>

<script type="text/javascript">

    function buscadiscos(field){

        //requisita o serviço PHP que vai listar os discos de uma banda, pelo id

        new Ajax.Request(´discos.php?id=´ + $F(field), {

            onSuccess: function(transport) {

                //alert(transport.responseText);

                $("discos").innerHTML = "";

                var discos = transport.responseText.split("|");

                for(var i=0; i<discos.length; i++) {

                    if(discos[i]=="")

                        continue;

                    var li = new Element("li").update(discos[i]);

                    $("discos").appendChild(li);

                }

            }

        });

        

    }

</script>

</head>

<body>



<h1>Exemplo - select aninhado</h1>



<form id="busca_discos" name="busca_discos" method="POST" action="#">

    <label>banda:</label>

    <select id="bandas" onchange="buscadiscos(this);">

        <option value="-1">selecione...</option>

    <?php

        //conecta ao banco

        $link = mysql_connect(´localhost´, ´root´, ´´);

        mysql_select_db(´exemplo_select´, $link);

        //monta string que seleciona todas as bandas

        $sql = "SELECT * FROM bandas";

        $result = mysql_query($sql);

        while ($row = mysql_fetch_array($result)) {

            echo("<option value=´" . $row["id"] . "´>" . $row["nome"] . "</option>");

        }

    ?>

    </select>

    <br /><br /><br />

    <label>discos:<label>

    <select id="discos"></select>

    

</form>





</body>

</html>



Segue o código da página discos.php:

 
<?php

    //conecta ao banco

    $link = mysql_connect(´localhost´, ´root´, ´´);

    mysql_select_db(´exemplo_select´, $link);

    //monta string que seleciona todos os discos de uma determinada banda

    $sql = "SELECT * FROM discos WHERE id_banda=" . $_GET["id"];

    $result = mysql_query($sql);

    while ($row = mysql_fetch_array($result)) {

        echo($row["nome"] . "|");

    }

?>

 

Vale ressaltar que a maneira de discos.php retirnar os dados foi a mais simples possível - e de menor qualidade. Para melhorar o código, seria interessante retornar um XML ou retornar os dados no formato JSON (tanto o PHP5 tem métodos nativos para codificar dados em formato JSON, quando a biblioteca JSON tem para decodificar os mesmos).