Selects aninhados – fazendo uma busca

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).

Ajax Libraries API

Mais uma vez, está lá o Google oferecendo serviços para facilitar a vida dos desenvolvedores.

Dessa vez, lançaram um serviço no qual hospedam algumas famosas bibliotecas javascript no servidor e que você pode usá-las de lá. Nesse momento, as bibliotecas disponíveis são: jQuery, prototype, script.aculo.us, MooTools e Dojo.



A forma de se utilizar é simples: primeiro você referencia a biblioteca javascript do Google:

<script src="http://www.google.com/jsapi"></script>

Depois, você precisa (1) carregar a biblioteca quer utilizar e, (2) dentro da função de callback dela, poderá utilizar a sua biblioteca normalmente, como se tivesse carregado da forma tradicional.

No exemplo abaixo, eu criei uma página que usa as bibliotecas prototype e script.aculo.us e faz uma div ser arrastável pela tela – um exemplo simples de como começar o uso da AJAX Libraries API do Google:

<!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>Ajax Libraries API</title>
<script src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
	//1 - carrega bibliotecas prototype e scriptaculous
	google.load("prototype", "1.6");
	google.load("scriptaculous", "1.8.1");
	//2 - na função de callback, crio uma div que pode ser arrastada usando um objeto da script.aculo.us
	google.setOnLoadCallback(function() {
		new Draggable($("drag"));
	});
</script>
<style type="text/css">
	div#drag {
		width:100px; height:50px; cursor:pointer; border:1px solid #FF0000;
	}
</style>
</head>
<body>
<div id="drag">drag me</div>
</body>
</html>

 

Qual a vantagem?

Você não precisa se preocupar em estar sempre com a última versão de cada biblioteca – o Google hospedará sempre a última versão estável, e caso você não especifique qual você quer usar, ele disponibilizará essa -, terá sempre acesso às últimas (e mais bacanas) bibliotecas javascript que estão disponíveis na web e não precisar se preocupar em setar cabeçalhos de cachê, entre outras vantagens.

No site do AJAX Libraries API, há explicações de como carregar todas as bibliotecas, e referências mais específicas. Vale a pena 🙂

Fonte: http://googlesystem.blogspot.com/2008/05/google-hosts-popular-javascript.html

Criando um auto-completar (ajax) com PHP e MYSQL

Escrevi esse texto acho que um ano atrás, para um outro site (acabou não dando em nada). Estou reeditando o mesmo 🙂

Vamos ver como fazer o básico para um auto-completar de um input (parecido com o Google Suggest). No nosso caso, vamos procurar por usuários em uma tabela de um banco de dados. Para isso, utilizarei PHP[bb] no lado do servidor. Mas, a linguagem do lado do servidor não é o que realmente importa. Uma funcionalidade que utiliza a metodologia o modelo ajax[bb] deve ser: um cliente javascript acessando um serviço que está no servidor (tanto faz a tecnologia).

No nosso caso, criei uma página PHP (name.php) que:

  • recebe um parâmetro para ser utilizado como filtro na nossa consulta: $name = $_GET["name"];
  • conecta ao banco de dados (no caso, utilizei o MySQL), acessando uma base que contenha uma tabela pm_users (essa tabela tem duas colunas, id e fullName);
  • efetua uma consulta à tabela utilizando $name como filtro na busca pelo campo fullName;
  • monta um array com os registros que satisfazem a busca;
  • retorna esse array no formato JSON (http://json.org/). JSON é um tipo de formato de troca de dados amplamente utilizado na web hoje em dia (tem vantagens e desvantagens com relação ao XML. Em um post futuro falo a respeito de cada um. Por hora, pode-se achar na web bons textos a respeito). Para transformar o array no formato JSON, utilizei uma classe do Zend Framework (http://framework.zend.com/).

Feito o nosso serviço no lado do servidor, vamos nos preocupar agora com a apresentação: criei uma página simples, que contém um formulário com um label e um campo input. E ainda uma área (div), a qual será usada para mostrar os resultados do auto-completar.

Depois, foi criada a formatação CSS. O mais importante no CSS é ver que a div#usersList tem sua posição definida como absoluta, e não está visível quando se entra na página.
Ela só ficará visível quando o usuário estiver digitando na caixa de texto e retornarem resultados.

Agora, temos toda a parte de layout pronta. Falta ligarmos isso com o serviço.
Como faremos? Há inúmeras formas.
A grande maioria das pessoas que utiliza PHP no lado do servidor, ou usa algum frameworks como o Sajax e o Xajax para criar a chamada às funções automaticamente, ou cria arquivos PHP que geram arquivos XML e no lado do cliente, criam na mão javascript para ler e tratar esse XML.
Eu quis, nesse nosso exemplo, dar uma outra forma a vocês de como fazer; na página 1, fiz uma página em PHP que retorna dados no formato JSON. Se eu fiz isso lá, no cliente vou ter que ler os dados também no formato JSON.

Antes de chegar lá, vamos ver como fazer para chamar o serviço criado.

  • um listener foi criado no onload do documento: sempre que o evento onkeyup for disparado na nossa caixa de texto, faremos a requisição no servidor;
  • caso o campo de texto não tenha pelo menos 3 caracteres, garantimos que a lista de resultados seja escondida e saímos da função (esperando que tenhamos 3 caracteres pelo menos);
  • se tiver pelo menos esses três, caracteres, definimos a URL do nosso serviço (no caso, a página PHP name.php) e os parâmetros a serem passados na requisição (no caso, o parâmetro name com o valor a ser usado para filtrar); Obs.: no caso, passamos um parâmetro "rnd=" + Math.round()*4 , isso é necessário para evitar cache na requisição, problema comumente encontrado nos browsers IE6-;
  • então, usamos o método Request do objeto Ajax da biblioteca Prototype (http://prototype.js). Note que esse método é uma espécie de wrapper para a criação do (objeto) XMLHttpRequest. Se você, usuário, quiser, pode continuar com sua implementação na mão do XMLHttpRequest. O impacto é mínimo. Segue link da documentação da API, dessa classe utilizada: http://www.prototypejs.org/api/ajax;
  • em caso de sucesso na requisição, a função de callback onSuccess é chamada, passando transport como parâmetro; transport possui o conteúdo do que foi retornado pelo request. No nosso caso, lembram-se dos dados no formato JSON? Por isso que utilizamos o método evalJSON(boolean) para transformar esses dados em formato compreensível pelo javascript. Obs.: evalJSON(boolean) é um método da Prototype. Se você tiver implementado o XMLHttpRequest, deve fazer a conversão utilizando uma biblioteca adequada. Uma boa procurada no Google lhe trará ótimos resultados a respeito.
  • uma vez com os dados transformados num formato compreensível pelo javascript (no caso, um array), só o que nos é necessário é percorrer esse array, sabendo que cada item do array possui um array de duas posições, onde a primeira é o id e a segunda o nome do usuário (olha só aí o porque o JSON é um belo formato de troca de dados: os dados que vieram do SELECT lá no PHP seguem a mesma ordem agora no javascript; não é preciso criar um XML, usar um DTD, percorrer nós, ver atributos, etc…). Voltando ao nosso array, ao percorrê-lo, criamos um elemento do tipo a para cada registro, e vamos definindo seus atributos (href, title, innerHTML…) e adicionando (appendChild) à lista, formando assim o nosso auto-completar

Pessoal, no final teremos uma página (ok, layout está bem simples, mas o propósito é mostrar a funcionalidade) onde o usuário vai digitando num campo input e através de uma rotina em PHP vão sendo feitas consultas no banco de dados, com filtro de usuários

Os arquivos estão disponíveis para

download

. Podem mexer, utilizar onde quiserem, modificar.

Web 2.0 sem Ajax?

Primeiro, vou agradecer @gserrano e @biab por poder dar meus pitacos aqui no odesenvolvedor.com.br 🙂

Estava pensando "o que seria um assunto bacana de se falar, que interessa a todos (desenvolvedores web) e que pode fomentar uma discussão?". Foi quando comecei a refletir sobre alguns acontecimentos na vida profissional: reuniões com clientes, bate-papo com colegas, desentendimentos com área comercial, etc…

E um grande ponto que sempre me leva ódio é quando alguém mistura o termo web 2.0 (considere você isso um termo, uma tendência, ou apenas mais um novo buzzword) com ajax (a metodologia); se seu site tem ajax, ele é web 2.0.



Não acho que seja necessário dar aulas sobre as diferenças entre um e outro (até porque a definição de ambos já foi feita em milhões de outros textos na internet), mas vou explicar rapidamente o que cada uma dessas palavras – ou termos – significa para mim, depois de anos trabalhando com web e nos últimos desses, muito ligado a eles:

web 2.0 é um apelido dado para a chamada revolução que ocorreu nos últimos 3 ou 4 anos, onde a internet deixou de ser um local onde o grande público visitava sites e recebia o conteúdo todo pronto – gerado por uma minoria – sem ter voz ativa, e passou a ser (ou está passando a ser, pois estamos sempre em constante mudança) um local onde o grande público pode contribuir com conteúdo, compartilhar conhecimento e ditar (ou seria melhor dizer seguir?) novos caminhos.

Ajax é uma metodologia de desenvolvimento, que combina algumas tecnologias – sendo a capacidade de se fazer requisições assíncronas a um servidor via javascript a base dela (não se esquecer que o xhtml, CSS, DOM, etc… fazem parte do pacote).



Tendo posto isso em pratos limpos, vêm o grande problema – aquele que me leva ao ódio em alguns momentos: onde está a relação de um com o outro?

Vamos ver… blogs, RSS, tags, (ia usar o termo taxonomia, mas ele diz tão pouco quando comparado ao termo tags…), redes sociais (orkut, facebook, myspace), wikis. Poucos ousam falar que esses itens não são ótimos exemplos de web 2.0. E claro que são… em todos eles, a tal revolução está presente; o usuário contribui com o conteúdo, ele escolhe para onde pode ir, o que quer fazer.

E aí? O que mais vou falar?

Talvez nem precisasse, é só analisar se algum exemplo desses necessita do uso de ajax para existir. Veja lá, são serviços que podem – ou não – se utilizar de pitadas de ajax (um suggest para as tags do del.icio.us por exemplo, ou um agregador de feeds como o Netvibes), mas que funcionariam na sua essência da mesma forma. O tal do ajax está lá não para ser o centro das atenções, mas sim para colaborar com o usuário; ajudar na sua experiência, facilitar seu uso, aumentar a velocidade do acesso, etc…

Então, vamos pensar: se não existisse o (tal do) ajax, nenhum dos conceitos abrangidos pelo termo web 2.0 seriam afetados – usuários continuariam conseguindo prover conteúdo, trocar informações, definir caminhos, fazer escolhas. Mas, o que seria do ajax sem a web 2.0? Seria apenas mais uma metodologia de desenvolvimento para web.

Ocorre uma grande confusão, e aí sou obrigado a dizer que grande responsabilidade é de nós, desenvolvedores, em colocar tecnologias acima de tudo. Acabamos nos ligando tanto às tecnologias que deixamos de lado os conceitos.



Resumindo: web 2.0 é focar na troca de informações, na colaboração entre os usuários, no conteúdo participativo. Qual tecnologia usar para fazer isso ser possível? Você escolhe 😉