27 maneiras de ser um melhor programador

Hoje o @chrisbenseler twittou sobre uma apresentação chamado  27 maneiras de ser um melhor programador PHP. São apenas tópicos específicos que servem para qualquer desenvolvedor – e algumas se aplicam para outras profissões.

Vale a pena ler até o final (em inglês) e rever alguns conceitos e atitudes que temos no dia a dia e que podemos mudar a fim de melhorar nossa carreira.

Ps: se você está pensnado em comentar reclamando que está em inglês e pedindo uma tradução eu tenho uma dica que vai te ajudar em qualquer carreira: estude inglês, recomendo o Live Mocha para isso. 🙂

Usando a prototype – passo 7 – lendo dados em formato JSON

Em mais um texto de série sobre o uso da prototype, vou mostrar como fazer para requisitar, via AJAX, dados em formato JSON e exibí-lo na tela.

JSON
Javascript Object Notation é um dos formatos de troca de dados mais utilizados atualmente. Tem como principais vantagens ser mais leve do que outros (como XML) e seguir o modelo de dados do javascript, por isso para aplicações AJAX é altamente recomendado.

O exemplo é simples, e consiste de uma tabela num banco de dados (utilizei MySQL), uma página que lista uma série de estados e dá ao usuário a opção de buscar as cidades desse estado com o seu respectivo DDD.
Segue, abaixo, o modelo da tabela com alguns poucos dados (obviamente, esse modelo nem de longe é o ideal, mas para efeitos de estudo, se aplica, uma vez que o foco é o JSON):

CREATE TABLE IF NOT EXISTS `cidades` (
  `estado` varchar(2) character set latin1 NOT NULL,
  `cidade` varchar(128) character set latin1 NOT NULL,
  `DDD` int(2) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin ROW_FORMAT=DYNAMIC;
--
-- Extraindo dados da tabela `cidades`
--
INSERT INTO `cidades` (`estado`, `cidade`, `DDD`) VALUES
(´sp´, ´Sao Paulo´, 11),
(´sp´, ´Santos´, 13),
(´sp´, ´Campinas´, 12),
(´rj´, ´Rio de Janeiro´, 21),
(´rj´, ´Buzios´, 23);

 
Então, criei uma página, em PHP, que recebe por POST o id do estado e retorna a lista de cidades e seus respectivos DDDs. Para mostrar no formato JSON, primeiro fazemos a consulta (mysql_query()), então criamos um array ($rows) e, percorrendo linha a linha do resultado (mysql_fetch_assoc()), jogamos cada entrada no array. Então, usamos a função nativa do PHP json_encode()

 

 

<?php
mysql_connect("localhost", "root", "******") or die(mysql_error());
mysql_select_db("exemplos") or die(mysql_error());
$sql = "SELECT cidade, DDD FROM cidades WHERE estado=´" . $_POST["estado"] . "´";
$result = mysql_query($sql);
$rows = array(); //cria array
//intera nos resultados e adiciona item a item no array
while($row = mysql_fetch_assoc($result)) {
$rows[] = $row;
}
echo json_encode($rows); //codifica para formato JSON
?>

Feito isso, vamos criar a página principal. Nela, criamos um formulário com a action apontando para a página recém criada e montamos um select com a lista dos estados (repito que esse não é o modelo adequado, deveria haver uma tabela com a lista de estados e a tabela com a lista de cidades usar essa como chave estrangeira, mas ter feito dessa maneira não atrapalha esse exemplo).
Ai começa o uso da prototype: no onload da página, dizemos que sempre que o select sofrer o evento onchange (ou seja, alguém selecionar um item da lista), vamos fazer a requisição usando o método Request do objeto Form da prototype (nesse post eu explico como fazer isso com detalhes).
No retorno da requisição, usamos o método evalJSON() da classe Array da prototype. A partir daí, o trabalho é manipulação de dados via javascript: usando o .each() do objeto Array, percorremos a lista e podemos acessar pelo nome da coluna da tabela os itens de cada registro, criando elementos de lista li e inserindo numa lista! Aí mais uma ótima vantagem do JSON: você pode acessar os dados de uma forma bem abstrata, usando os mesmos nomes dados na base de dados como se fossem atributos de um objeto.

 

<!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=UTF-8" />
<title>Prototype com PHP - usando json</title>
<script src="http://www.prototypejs.org/assets/2008/1/25/prototype-1.6.0.2.js"></script>
<script type="application/javascript">
    //no onload da página, cria listener para o select dos estados
    Event.observe(window , "load", function() {
        Event.observe($("estados"), "change", function() {
            //chama método para listar as cidades a partir do estado selecionado
            $("buscaCidades").request({ 
                onComplete: function(transport){
                    //decodifica JSON
                   
                    var list = $("cidades");
                    //limpa a lista
                    list.innerHTML = "";
                    //percorre lista de cidades com seu DDD usando o iterator each da classe Array da prototype
                    transport.responseText.evalJSON(true).each(function(city) {
                        var li = new Element("li").update(city.cidade + " (" + city.DDD + ")");
                        list.insert(li);
                    });
                }
            });
           
        });
       
    });
   
</script>
</head>
<body>
<h1>Teste para trazer lista de cidades com o seu DDD a partir de um estado</h1>
<form id="buscaCidades" action="cidadeddd_json.php" method="POST">
    <label for="estados">estado:</label>
    <select name="estado" id="estados">
    <option value="-1">selecione um estado...</option>
    <?php
    //conecta ao banco e retorna a lista de estados a partir da tabela de cidades
    mysql_connect("localhost", "root", "******") or die(mysql_error());
    mysql_select_db("exemplos") or die(mysql_error());
   
    $sql = "SELECT estado FROM cidades GROUP by estado";
   
    $result = mysql_query($sql);
    while($row = mysql_fetch_array( $result )) {
    ?>
    <option value="<?php echo $row["estado"];?>"><?php echo $row["estado"]; ?></option>
    <?php
    }
    ?>
    </select>
</form>
<h2>Lista de cidades e seu DDD</h2>
<ul id="cidades">
</ul>
</body>
</html>
 

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

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.