xml to mysql: Transformando um arquivo XML em queries SQL (e blablabla)

7 07 2007

xml to mysql: Como fazer o reverso indicado aqui: mysql to xml: Como transformar um resultado de uma query para XML ( de forma simples ) ( de forma simples )

Sugerido aqui, por Robertson Matos

Para o script, vamos utilizar um banco de dados de exemplo. O banco terá a seguinte estrutura:

-- criamos o banco de dados, caso ainda nao exista
CREATE DATABASE IF NOT EXISTS XML2MYSQL;

-- selecionamos o banco de dados
USE XML2MYSQL;

-- criamos a tabela se nao existir
CREATE TABLE IF NOT EXISTS exemplo (
    id_exemplo INT(11) NOT NULL AUTO_INCREMENT,
    descricao VARCHAR(32) NOT NULL,
    PRIMARY KEY(id_exemplo)
)ENGINE=INNODB;

O XML de exemplo é este:
demo.xml


<?xml version=“1.0”?>
<resultset>
    <line>
        <id_exemplo>1</id_exemplo>
        <descricao>Primeiro exemplo</descricao>
    </line>
    <line>
        <id_exemplo>2</id_exemplo>
        <descricao>Segundo exemplo</descricao>
    </line>
    <line>
        <id_exemplo>3</id_exemplo>
        <descricao>Terceiro exemplo</descricao>
    </line>
</resultset>

E o script é este:


<?php
    
// arquivo xml2mysql.php

    // definimos informacoes para conexao ao banco de dados:
    $banco   ‘xml2mysql’;             // nome do banco
    
$host    ‘localhost’;             // host
    
$usuario ‘root’;                  // usuario
    
$senha   ;               // senha
    
    // connectamos ao host e selecionamos o banco
    
mysql_connect($host$usuario$senha);
    
mysql_select_db($banco);

    // esta variavel sera a query utilizada para insercao dos
    // dados no banco, tendo o %d substituido pelo id_exemplo
    // e o %s substituido pela descricao
    
$query ‘insert into exemplo (id_exemplo, descricao) values (%d, “%s”)’;
    
    
// carregamos o conteudo do arquivo XML
    
$xml file_get_contents(‘demo.xml’);
    
    
// transformamos o XML em um objeto, para que possamos trabalhar
    // de forma mais simples com ele
    
$sxml = new SimpleXMLElement($xml);
    
    
// aqui iteramos por todo o XML:
    // a cada iteracao, $line ira conter um objeto to tipo
    // SimpleXMLElement, sendo o equivalente a:
    //
    //  <line>
    //      <id_exemplo>1</id_exemplo>
    //      <descricao>Primeiro exemplo</descricao>
    //  </line>
    //
    
foreach ($sxml as $linhaAtual) {
        
// aqui vamos obter cada item do xml que seria referente
        // ao campo da tabela.
        // Necessario cast pelo fato de que a propriedade do objeto
        // tambem é um objeto do tipo SimpleXMLElement
        
$id        = (int) $linhaAtual->id_exemplo;
        
$descricao = (string) $linhaAtual->descricao;
        
        
// aqui preparamos a query para ser utilizada
        
$tmpQuery sprintf($query$id$descricao);
        
        
// exibimos a query que será executada
        
echo sprintf(‘Executando query: %s%s’$tmpQuery“\n”);

        // e aqui executamos a query
        
mysql_query($tmpQuery);
    }

Sem controle de erros, prevenção de sql injection, blablabla, apenas para ilustrar, como de costume.
Executando temos:

$ php xml2mysql.php
Executando query: insert into exemplo (id_exemplo, descricao) values (1, “Primeiro exemplo”)
Executando query: insert into exemplo (id_exemplo, descricao) values (2, “Segundo exemplo”)
Executando query: insert into exemplo (id_exemplo, descricao) values (3, “Terceiro exemplo”)

E conferindo no banco:

mysql> select * from exemplo;
+————+——————+
| id_exemplo | descricao |
+————+——————+
| 1 | Primeiro exemplo |
| 2 | Segundo exemplo |
| 3 | Terceiro exemplo |
+————+——————+
3 rows in set (0.00 sec)

É isso ai, valeu pela sugestão Robertson

Arquivos:
xml2mysql.php
xml2mysql.sql
demo.xml





Validação de campos usando XML

23 03 2007

Há quanto tempo pessoas!
Pois é, a vida está bastante corrida, e o tempo anda curto… quando sobra algum, a gente acaba dormindo : | Meleca viu… Mas, lamentações a parte, vamos falar sobre o que realmente interessa: PHP!
Bom, como ando meio sem criatividade para postar, decidi que vou demonstrar uma maneira de realizar validação de campos, utilizando xml para caracterizar essa validação, fazendo com que você não precise sair que nem louco caçando as validações no meio do seu código o dia que precisar alterar alguma. Esse é o tipo de validação que o E. Silva e eu temos utilizado em nosso framework do qual ele já comentou ai em alguns comentários (frase linda).
Algumas idéias aqui, poderão parecer confusas de início para quem não está muito acostumado com PHP, mas como sempre digo, se tem alguma duvida, fique a vontade para mandar email ou deixar comentário que a gente resolve como pode.
Como sempre, gosto de começar com exemplos, então, vamos começar com o XML de exemplo:

validador.xml

<validator>
    <field name=‘nome’ validation=‘validator::isFilled’ when=‘insert,update’ />
    <field name=‘cpf’ validation=‘validator::isCpf’ when=‘insert,update’ />
    <field name=‘data’ validation=‘validator::isData’ when=‘insert’ />
</validator>

Esse ai será o xml que iremos usar para validar nossos campos. Vamos entender algumas coisas:
A propriedade ‘name’, identifica o nome do campo que será validado
A propriedade ‘validation’, define o método que será utilizado para validação
A propriedade ‘when’ define quando a validação deverá ocorrer. Essa propriedade será identificada através da ação que o botão do formulário fornece.

Os exemplos que serão trabalhados, utilizam o método POST para envio dos dados, e tem o action definido na própria página. Preparem-se, pois hoje teremos bastante código.
Vamos dar uma olhada agora, no código do formulário, que ficará no script que chamaremos de index.php

index.php

<form method=“POST”>
<input type=“text” name=“nome” /><br />
<input type=“text” name=“cpf” /><br />
<input type=“text” name=“data” /><br />
<!– agora vem o botão de submit, que identificará a ação que ocorre –>
<input type=“submit” name=“acao” value=“Insert” />
</form>

Esse script ainda não está pronto. Falta ainda o código PHP do mesmo. Agora, vou esclarecer um pouco melhor como será o funcionamento do script.
Todo o formulário, será (ou não), preenchido, e será feito o envio das informações ao se clicar no botão de Inserir. Quando o script receber esses dados, será invocada a classe, que lê o xml de validação, e aplica essa validação aos campos que foram recebidos. Os campos serão validados conforme descrição feita pelo XML, e a partir dai serão geradas as mensagens do sistema. O script que será demonstrado é um exemplo, para dar uma idéia de como se utilizar esse método de validação. Não estou demonstrando exatamente igual ao funcionamento do nosso framework, pelo simples fato, de que eu iria precisar de muitas classes do framework para isso, e então deixaria de ser um post de blog, para virar um livro : |
Veja então a classe que irá fazer o parse do arquivo xml, e validará as entradas fornecidas pelo usuário:

action.class.php


<?php

class Action {

    // Essa propriedade da classe, ira conter
    // o resultado da validacao de cada um dos
    // campos.
    
private $validacao = array( );

    // Essa propriedade ira dizer se ocorreu algum erro
    // para o script 
    
private $error null;

    // Retorna o valor da propriedade $error
    
public function getError( ) {
        return 
$this->error;
    }

    // Retorna o valor da propriedade $validacao
    
public function getValidacao( ) {
        return 
$this->validacao;
    }

    public function run( ) {
        
// normalmente, possuimos uma classe para trabalhar
        // com metodo POST e GET. No nosso caso, de forma a 
        // simplificar a quantidade de codigo, vamos usar a 
        // variavel $_POST diretamente

        // Essas aqui serao as acoes que iremos validar. Como
        // ja comentado, as acoes sao definidas atraves do valor
        // do botao que faz o metodo POST
        $validActions = array(
                            
'insert',
                            
'update',
                            
'delete' 
                        
);

        $acao strtolower$_POST['acao'] );
        if( 
in_array$acao $validActions ) ) {
            
// Inicializar a variavel de controle de erro
            
$this->error true;

            // Se chegou nesse ponto, significa que a acao realizada
            // foi uma das acima. Agora deve-se carregar o xml e começar a
            // fazer o seu parsing
            
$xml simplexml_load_file'validador.xml' );

            // A partir de agora, vamos avaliar cada uma das linhas do xml
            // e realizar a validacao.
            
foreach( $xml->field as $campo ) {

                // Aqui, vamos procurar pelo campo atual que encontramos no xml
                // dentro do array $_POST. Se o campo for encontrado, iremos
                // validar o valor que nos foi enviado.
                
if( array_key_exists( (string)$campo['name'], $_POST ) ) {

                    // Otimo, encontramos o campo no array POST. Porem antes
                    // de validarmos o campo, precisamos verificar se ele
                    // deve ser validado na acao que esta acontecendo.
                    // Lembra-se da propriedade 'when' no xml? Eh aqui
                    // que ela entra, nos informando se o campo deve ou nao
                    // ser validado. As acoes devem ser separadas por uma ','
                    // no xml
                    
$whenToValidate explode(','$campo['when'] );
                    if( 
in_array$acao$whenToValidate ) ) {

                        // Finalmente chegamos! Chegou aqui, entao esta na hora
                        // de validar o campo de acordo com o que esta no xml.
                        // O conteudo especificado na propriedade 'validation'
                        // do xml, define um metodo estatico a ser chamado para
                        // validar o valor que foi enviado no metodo post
                        // nos permitindo assim, assumit que esse metodo recebe
                        // ao menos 1 parametro, que eh o valor a ser validado
                        // Veja a classe com os metodos de validacao, para
                        // entender exatamente o que acontece
                        
$codigo sprintf('$ret = %s( $_POST["%s"] );',
                                          (string)
$campo['validation'],
                                          (string)
$campo['name']
                                         );

                        // Suponto que estamos validando o campo 'nome', que
                        // da maneira como está descrito no xml do tutorial,
                        // teremos $codigo valendo algo como:
                        // $ret = validator::isFilled( $_POST["nome"] );
                        // Executa-se o código de validação agora. A variavel
                        // $ret ira conter o resultado da validacao.
                        
eval( $codigo );

                        // Caso $ret seja diferente de true, estou assumindo
                        // que o retorno é entao uma mensagem de erro
                        
if( $ret === true ) {
                            
$this->validacao[(string)$campo['name']] = true;
                        } else {
                            
$this->error true;
                            
$this->validacao[(string)$campo['name']] = $ret;
                        }
                    }
                }
            }
        }
    }
}

?>

Com esse código em mãos, precisamos também ter a classe que faz validação do conteúdo digitado nos campos. Como foi denifido no xml, a classe que estamos usando é a classe Validator. A que irei apresentar, faz validações hipóteticas, não sendo recomendado o uso delas, da forma que estão. Veja o código:

validator.class.php


<?php

class Validator {

    // Método que verifica se há algum valor em $valor
    
public static function isFilled$valor ) {
        if( empty( 
$valor ) )
            return 
'Campo nao pode ser vazio';

        return true;
    }

    // Metodo que iria validaro valor, para saber se este
    // eh um cpf valido
    
public static function isCpf$valor ) {
        if( 
$valor == '11111111111' )
            return 
'CPF invalido';

        return true;
    }

    // Metodo que verificaria se a data informada
    // eh valida
    
public static function isData$valor ) {
        
$data explode('/',$valor);
        if( 
sizeof$data ) != )
            return 
'Data invalida';

        return true;
    }

}

?>

Já está quase tudo pronto, agora basta adicionarmos o código em nosso index.php, que fará a validação dos campos. Lembra-se daquele nosso primeiro index.php não é mesmo? Ele deve ficar assim agora:

index.php


<?php

include_once('validator.class.php');
include_once(
'action.class.php');
$action = new Action( );
$action->run( );

if( $action->getError( ) === true ) {
    
$camposInvalidos $action->getValidacao( );
    foreach( 
$camposInvalidos as $campo=>$e ) {
        if( 
$e !== true )
            
printf('Erro: campo %s - %s <br>'$campo$e ); 
    }
}

?>

<form method="POST">
    <input type="text" name="nome" /><br />
    <input type="text" name="cpf" /><br />
    <input type="text" name="data" /><br />
    <!-- agora vem o botão de submit, que identificará a ação que ocorre -->
    <input type="submit" name="acao" value="Insert" />
</form>

Nestes exemplos, eu levei em conta todos os arquivos estão em um só diretório, como pode ser observado pelos include_once que faço no início do script.

Esclarecendo tudo então:

  • O arquivo xml é o responsável por descrever a validação
  • A propriedade validation contém o nome da classe e do método, como se fossem uma chamada estática Classe::metodo
  • A propriedade when define em quais acoes o campo deve ser validado, e essa ações são separadas por ‘,’
  • A propriedade name define o nome do cmapo que está sendo validado

Bom, é isso!
Como de costume, os arquivos para visualização do código seguem abaixo, pois o wordpress é tosco, e zoa todo o código, para copiar e colar.
Qualquer dúvida/comentário/sugestão/elogio/doações, não deixe de contatar-me : )

[]s

Index.php
Action.class.php
Validator.class.php
Validador.xml





GeoIP: Como verificar a localização de um endereço IP ( com figuras )

7 03 2007

Sim, com figuras : D

Podemos utilizar a versão lite do GeoIP para verificamos de onde vem um visitante. Apenas vale observar que a precisão das informações desta versão não é a mais alta possível.

Se estiver utilizando linux (ou algum bsd), o processo é bastante simples (não sei em ambiente windows, lá é tudo muito difícil…). Vejamos:

  1. Efetue o download do arquivo com informações sobre cidades. O arquivo se encontra neste link. Aqui é o link direto para ele.

    Após efetuar o download, basta descompacta-lo com o comando:

    $ gunzip GeoLiteCity.dat.gz

  2. Utilizaremos o pacote do Pear Net_GeoIP para as requisições. A instalação é bastante simples:

    # pear install Net_GeoIP-beta

  3. Neste ponto, já estamos pronto para utilizar a extensão. Vejamos alguns exemplos de código em PHP:


    <?php
        
    // arquivo ipinfo.php
        
        
    require_once ‘Net/GeoIP.php’;

        // Em um outro codigo foi explicado o funcionamento de blocos
        // try / catch
        
    try {
            
    // instanciamos a classe Net_GeoIP, passando como parametro
            // o path daquele arquivo baixado anteriormente
            
    $gip Net_GeoIP::getInstance(‘GeoIPCity.dat’);
            
            
    // verificamos se foi executado corretamente.
            // caso nao tenha sido, gera uma exception
            
    if ( $argc != )
                throw new 
    Exception(‘Uso: php ip2city IP’);
            
            
    // o metodo lookupLocation retorna um objeto do tipo
            // Net_GeoIP_Location, que contem informacoes sobre a localizacao
            // para um determinado ip, passado como parametro para o metodo    
            
    $location $gip->lookupLocation($argv[1]);
            
            
    // finalmente, exibimos as informacoes
            
    echo sprintf(‘Pais: %s%s’$location->countryName“\n”);
            echo 
    sprintf(‘Cidade: %s%s’$location->city“\n”);

        } catch ( Exception $e ) {
            echo 
    sprintf(‘Erro: %s%s’$e->getMessage(), “\n”);
        }
    ?>

    $ host uol.com.br
    uol.com.br has address 200.221.2.45
    uol.com.br mail is handled by 10 mx.uol.com.br.
    $ php ipinfo.php 200.221.2.45
    Pais: Brazil
    Cidade: São Paulo
    $ host http://www.belgium.be
    http://www.belgium.be has address 193.191.209.193
    http://www.belgium.be mail is handled by 10 pop.fgov.be.
    $ php ipinfo.php 193.191.209.193
    Pais: Belgium
    Cidade: Brussels
    $ host google.com
    google.com has address 64.233.167.99
    $ php ipinfo.php 64.233.167.99
    Pais: United States
    Cidade: Mountain View

    Vamos ver nesse segundo exemplo como exibir em uma mapa a localização do endereço IP informado. Utilizaremos a API do yahoo para isso:


    <?php
        
    // arquivo ipmap.php

        // autor: e silva
        
        require_once ‘Net/GeoIP.php’;

        // observe que esta sendo utilizada uma chave demo. O yahoo diz que nao
        // se pode utilizar essa chave e que e’ necessario criar uma propria.
        // veja mais em http://developer.yahoo.com/maps/
        
    $yahooKey ‘YahooDemo’;
        
        
    $msg ;
        
        
    // Em um outro codigo foi explicado o funcionamento de blocos
        // try / catch
        
    try {

            // instanciamos a classe Net_GeoIP, passando como parametro
            // o path daquele arquivo baixado anteriormente
            
    $gip Net_GeoIP::getInstance(‘GeoIPCity.dat’);

            // verificamos se foi informado algum IP. Se nao foi,
            // utilizaremos o ip de quem esta acessando o script
            
    if ( !isset($_REQUEST[‘ip’]) )
                
    $_REQUEST[‘ip’] = $_SERVER[‘REMOTE_ADDR’];
            
    $ip $_REQUEST[‘ip’];
            
            
            
    // o metodo lookupLocation retorna um objeto do tipo
            // Net_GeoIP_Location, que contem informacoes sobre a localizacao
            // para um determinado ip, passado como parametro para o metodo    
            
    $location $gip->lookupLocation($ip);
            if ( !
    $location )
                throw new 
    Exception(‘Ip invalido’);
            
            
    // definimos algumas informacoes que serao utilizadas mais 
            // a frente no script
            
    $latitude $location->latitude;
            
    $longitude $location->longitude;
            
    $msg  sprintf(‘Pais:      <b>%s</b><br />’$location->countryName);
            
    $msg .= sprintf(‘Cidade:    <b>%s</b><br />’$location->city);
            
    $msg .= sprintf(‘Latitude:  <b>%s</b><br />’$location->latitude);
            
    $msg .= sprintf(‘Longitude: <b>%s</b><br />’$location->longitude);
        } catch ( 
    Exception $e ) {
            echo 
    sprintf(‘Erro: %s%s’$e->getMessage(), “\n”);
            die;
        }
        
        
    // e exibimos o mapa no navegador
    ?>

    <html>
        <head>
            <script type=”text/javascript” src=”http://api.maps.yahoo.com/ajaxymap?v=3.0&appid=<?=$yahooKey?>“></script>
        </head>
        <body>
            <?=$msg?>
            <div id=”map” style=”height:580px;width:780px;”></div>
            <script type=”text/javascript”>
                var position = new YGeoPoint(<?=$latitude?>,<?=$longitude?>);
                var map = new YMap(document.getElementById(‘map’));

                var loc = new YMarker(position);

                map.drawZoomAndCenter(position, 5);
                map.addTypeControl();
                map.setMapType(YAHOO_MAP_HYB);
                map.addOverlay(loc);
                map.addZoomLong();
                map.addPanControl();
            </script> 
        </body>
    </html>

    map to ip

    O script acima, apesar de não ter o html comentado, é bem simples de entender. Num post futuro podemos ver mais detalhadamente o uso de mapas usando API do yahoo, visto que o propósito neste post não é esse.

    Então é isso, é bastante simples a verificação da localização de um visitante através do endereço IP, mesmo utilizando a versão lite do geoip, o funcionamento é bem satisfatório.

    Arquivos:
    ipinfo.php
    ipmap.php

    É isso.





Last.fm + PHP: Conheça novos artistas e novas músicas

4 03 2007

Cansado de ouvir as mesmas músicas ? Que tal escrever um pequeno script para obter uma lista de artistas similares aos que você costuma ouvir ?

Para isso utilizaremos informações disponibilizadas pela Last.FM

Inicialmente, criamos uma classe, bem simples, para obter as informações. Uma breve explicação do funcionamento desta classe está nos comentários.


<?php
    
// arquivo similarartist.class.php
    
    /**
    * Classe que ira obter as informacoes de artistas similares
    *
    * @author e silva <heap@heap.com.br>
    */
    
class SimilarArtist {
        
/**
        * URL onde serao buscadas as informacoes
        * @var string
        */
        
private $url ;
        
        
/**
        * Nome do artista informado na instanciacao da classe
        * @var string
        */
        
private $artist ;
        
        
/**
        * Lista com os artistas similares encontrados
        * @var array
        */
        
private $similarArtists = array();
        
        
/**
        * Construtor da classe
        *
        * Inicializa as propriedades “url” e “artist” e chama o metodo
        * responsavel pelo carregamento da lista com os artistas similares
        *
        * @param string $artist Nome do artista desejado
        */
        
public function __construct($artist)
        {
            
$this->artist $artist;
            
$this->url sprintf(http://ws.audioscrobbler.com/1.0/artist/%s/similar.xml&#8217;$artist);
            
$this->load();
        }
        
        
/**
        * Efetua carregamento do artistas similares ao informado
        *
        * @throw Exception
        */
        
private function load()
        {
            
// obtem o conteudo do arquivo com as informacoes de artistas
            // similares.
            // Caso nao consiga, gera uma exception
            
$content = @file_get_contents($this->url);
            if ( !
$content )
                throw new 
Exception (‘Could not load url’);

            // caso o conteudo do arquivo contenha uma string informando que
            // o artista nao existe, tambem gera uma exception
            
if ( strstr($content‘No artist exists with this name’) )
                throw new 
Exception (sprintf(‘Artist “%s” not found’$this->artist));

            // o conteudo do arquivo esta em formato XML. Transforma-se entao
            // este conteudo em uma instancia da classe SimpleXMLElement. Caso
            // ocorra algum erro, uma outra exception e’ gerada
            
$xml = @simplexml_load_file($this->url);
            if ( !
$xml )
                throw new 
Exception (‘Could not load url’);

            // efetua uma iteracao por todos os itens do objeto criado anteriormente,
            // populando a propriedade “similarArtists” desta classe.
            // note que e’ criado um array de arrays com dois indices: “name” e “image”:
            // o primeiro indice e’ o nome do artista similar encontrado e o segundo
            // contem uma url com uma imagem do artista. Simples…
            
foreach ( $xml->artist as $similar )
                
$this->similarArtists[] = array( 
                                            
‘name’  => (string) $similar->name
                                            
‘image’ => (string) $similar->image
                                          
);
        }
        
        
/**
        * Retorna uma lista com todos os artistas encontrados
        *
        * @return array Array de arrays com todos os artistas similares encontrados
        */
        
public function getAll()
        {
            return 
$this->similarArtists;
        }
    }

Após a criação da classe, que por sinal é bastante simples, criaremos 2 exemplos de uso: Um utilizando a linha de comando e um utilizando um script acessado via navegador. Ambos estão comentados também. Vejamos o primeiro:


<?php
    
// incluimos a definicao da classe
    
include ‘similarartist.class.php’;

    // como a classe SimilarArtist gera exceptions e nao desejamos que
    // elas sejam simplesmente jogadas na tela, iremos captura-las.
    // Resumidamente, este bloco funciona assim:
    //
    // tente fazer o seguinte {
    //      lista de itens que devem
    //      ser executados. Alguns deles
    //      podem gerar uma exception
    // } capture as excecoes {
    //      se estamos aqui, significa que no bloco
    //      anterior foi gerada uma exception. Fazemos o
    //      tratamento necessario nesta parte.
    // }
    //
    // Bastante simples. Futuramente havera por aqui um pequeno tutorial
    // sobre exceptions
    
try {
        
// aqui obtemos o nome do artista informado na linha de comando
        // ha outras formas de se fazer o que faco aqui, por exemplo, utilizando
        // getopt. Caso nao encontre o argumento necessario, gera uma exception, que
        // sera capturada mais abaixo
        
$pos array_search(‘–artist’$argv);
        if ( !
$pos || !isset($argv[$pos+1]))
            throw new 
Exception(‘Uso: php cli.php –artist nome do artista’);
        
$artist implode(‘+’array_slice($argv$pos+1$argc));

        // instancia a classe com o nome do artista informado e exibe 
        // informacao de quantos foram encontrados
        
$sa = new SimilarArtist($artist);
        
$list $sa->getAll();
        echo 
sprintf(‘Encontrados %s artistas similares. Exibindo os 5 primeiros:%s’sizeof($list), “\n”);

        // e finalmente, exibe a lista de artistas
        
$cont 1;
        foreach ( 
$list as $similar ) {
            echo 
sprintf(‘%s – %s%s’$cont++, $similar[‘name’], “\n”);
            if ( 
$cont ) break;
        }
    
// como explicado anteriormente, capturamos qualquer exception que possa ter 
    // sido gerada
    
} catch ( Exception $exc ) {
        echo 
sprintf(‘Ocorreu um erro: %s%s%s’“\n”$exc->getMessage(), “\n”);
    }

Executando temos:

$ php cli.php –artist velhas virgens
Encontrados 100 artistas similares. Exibindo os 5 primeiros:
1 – Raul Seixas
2 – Raimundos
3 – Ultraje a Rigor
4 – Matanza
5 – Engenheiros do Hawaii

Segundo exemplo: Script web:


<?php
    
// arquivo web.php

    // veja explicacao no script anterior, o funcionamento e’ bem similar
    include ‘similarartist.class.php’;
    
    
    try {
        if ( !isset(
$_REQUEST[‘artist’]) )
            throw new 
Exception(‘Artista nao informado’);
        
$sa = new SimilarArtist($_REQUEST[‘artist’]);
        
$list $sa->getAll();
        echo 
sprintf(‘Exibindo <strong>%s</strong> artistas similares a <strong>%s</strong>’sizeof($list), $_REQUEST[‘artist’]);
        foreach ( 
$list as $artist ) {
          echo 
‘<div style=”float:left;margin-right:10px;”>’;
          echo 
sprintf(‘    <h3>%s</h3>’utf8_decode($artist[‘name’]));
          echo 
sprintf(‘    <img src=”%s” alt=”%s” />’$artist[‘image’], utf8_decode($artist[‘name’]));
          echo 
‘</div>’;
        }
    } catch ( 
Exception $exc ) {
        echo 
sprintf(‘Ocorreu um erro: %s%s%s’“\n”$exc->getMessage(), “\n”);
    }
?>

Executando temos:

web

Arquivos:
similarartist.class.txt
cli.txt
web.txt

É isso ai.





Cadastro com confirmação por email

26 02 2007

O leitor Erick de Oliveira nos pediu um tutorial sobre cadastro com
confirmação por email. Irei demonstrar de maneira bem simples e rápida uma
maneira de como criar um cadastro desse tipo e tentar sugerir algumas idéias.
Os exemplos irão usar o MySQL como database.
Aproveitando o embalo de já estar falando de MySQL, vamos construir então a
tabela que nos auxiliará nessa tarefa:


create table cadastro (
id_cadastro int not null primary key auto_increment,
nome varchar(50),
email varchar(50),
login varchar(30),
senha varchar(32),
data_ts varchar(14),
uid varchar(50),
ativo bool default 0
);

Nessa tabela, serão salvas as informações básicas de login do usuário. Quero
chamar atenção especial para os campos ‘data_ts’, ‘uid’ e ‘ativo’. Esses serão
os campos que usaremos como controle, para validar o usuário, após ele receber
o email de confirmação de seu cadastro.
O campo uid, irá armazenar um id unico, gerado pela função uniqid do
PHP, e esse id será usado em conjunto com o campo de data_ts, para validarmos
o cadastro do usuário, e ativarmos a sua conta. É mais simples de explicar
como funcionará, mostrnado um pouco de código.
(Obs: Não irei me preocupar aqui, em verificar se o login já não está em uso
no sistema por alguém, ou se as informações foram corretamente preenchidas, já
que a ideia aqui é demonstrar como validar o cadastro através de um email de
confirmação).

Cadastro.php


<?php

// Vou assumir que o arquivo conectar.php existe, e que ele e o responsavel
// por se conectar a seu database
include_once('conectar.php'); 

// Vou assumir que os campos foram preenchidos todos corretamente
// e que ninguem vai tentar se aproveitar do formulario para SQL Injection
// ou coisas do genero

if( isset( $_POST['enviar'] ) ) {

    $nome $_POST['nome'];
    
$email $_POST['email'];
    
$login $_POST['login'];
    
$senha md5$_POST['senha'] );
    
$uid uniqidrand( ), true );
    
$data_ts time( );
    
$ativo 0;

    $sql "insert into cadastro ( id_cadastro, nome, email, login, senha,
data_ts, uid,
ativo ) "
;
    
$sql .= "values
('', '$nome','$email','$login','$senha','$data_ts','$uid','$ativo')"
;

    if( ! mysql_query$sql ) ) {
        echo 
"Houve um erro inserindo o registro ".mysql_error( );
    } else { 
// Registro inserido com sucesso, mandar email

        $id mysql_insert_id$con );

        // Criar as variaveis para validar o email
        
$url =
sprintf'id=%s&email=%s&uid=%s&key=%s',$idmd5($email), md5($uid),
md5($data_ts)
);

        $mensagem 'Para confirmar seu cadastro acesse o link:'."\n";
        
$mensagem .= sprintf('http://www.dominio.com.br/ativar.php?%s',$url);

        // enviar o email
        
mail$email'Confirmacao de cadastro'$mensagem );

        echo "Registro inserido com sucesso";
    }
}

?>

<form method="POST">

    Nome:<input type="text" name="nome"><br>
    Email:<input type="text" name="email"><br>
    Login:<input type="text" name="login"><br>
    Senha:<input type="password" name="senha"><br>
    <br>
    <input type="submit" name="enviar" value="Cadastrar">

</form>

O formulário é bastante simples, e eu gostaria de dar destaque a linha:
$url = sprintf( ‘id=%s&email=%s&uid=%s&key=%s’,$id, md5($email), md5($uid),
md5($data_ts) );

Veja que essas são as variáveis que identificam o usuário que acaba de se
cadastrar. Quando a url para validação for acessada, iremos conferir se o os
dados de unique id e a data conferem com o email especificado, para poder
então ativar o cadastro. O email e data, são passados como hash md5, para
proteger essas informações de quem as possa estar vendo. A variável id
é quem identificará com qual registro na tabela essas informações devem ser
comparadas. O registro será ativado, apenas caso todas as informações
cadastradas sejam iguais as informações vindas pela URL, dessa forma, se
alguém tentar ativar um cadastro sem ser o verdadeiro dono da informação, não
poderá faze-lo, a menos que conheça o segundo exato em que o cadastro foi
feito, o email no qual o cadastro foi feito e a unique id do usuario.
Vamos ver então, como fica o código para ativar o cadastro.

Ativar.php


<?php

// Novamente, nao irei fazer nenhum tipo de checagem para validar os dados
// em busca de SQL Injection ou coisas do genero. Nao se esqueca voce de fazer
// isso.

// Conectar no banco de dados
include_once('conectar.php');

// Dados vindos pela url
$id $_GET['id'];
$emailMd5 $_GET['email'];
$uidMd5 $_GET['uid'];
$dataMd5 $_GET['key'];

//Buscar os dados no banco
$sql "select * from cadastro where id_cadastro = '$id'";
$sql mysql_query$sql );
$rs mysql_fetch_array$sql );

// Comparar os dados que pegamos no banco, com os dados vindos pela url
$valido true;

if( $emailMd5 !== md5$rs['email'] ) )
    
$valido false;

if( $uidMd5 !== md5$rs['uid'] ) )
    
$valido false;

if( $dataMd5 !== md5$rs['data_ts'] ) )
    
$valido false;

// Os dados estão corretos, hora de ativar o cadastro
if( $valido === true ) {
    
$sql "update cadastro set ativo='1' where id_cadastro='$id'";
    
mysql_query$sql );
    echo 
"Cadastro ativado com sucesso!";
} else {
    echo 
"Informacoes invalidas";
}

?>

A partir daí o cadastro já pode ser ativado. Agora quando o usuário for se
logar no sistema, basta verificar se o valor do campo ativo na tabela
para aquele usuário, vale 1. Caso sim, significa que o usuário já teve sua
ativação realizada.

Espero que o texto possa ter ajudado, e qualquer dúvida, basta deixar um
comentário ai : )
Abaixo estão os links para os arquivos com os códigos dos exemplos, pois o
Wordpress faz o favor de estragar as aspas, e consequentemente o código : |

[]s

Cadastro.txt
Ativar.txt





Upload de multiplos arquivos com PHP

22 02 2007

Fala pessoal!
A pedido do leitor Rodrigo Almeida, vou escrever aqui um mini tutorial de como criar um formulário para upload de multiplos arquivos.
Para começar então, vou demonstrar como se cria um formulário para upload de um único arquivo, e depois passaremos para upload de multiplos arquivos.


<?php

if( isset( $_POST['enviar'] ) ) {

    $erro '';
    
$pathToSave '/tmp/';

    // A variavel $_FILES é uma variável do PHP, e é ela a responsável
    // por tratar arquivos que sejam enviados em um formulário

    if( $_FILES['arquivo']['name'] != '' ) {
        
$arquivoTmp $_FILES['arquivo']['tmp_name'];
        
$arquivo $pathToSave.$_FILES['arquivo']['name'];

        // Copia o arquivo para o sistema
        
if( !move_uploaded_file$arquivoTmp$arquivo ) ) {
            
$erro 'Erro no upload. Verifique as permissoes do diretorio';
        }
    } else {
        
$erro 'É necessario escolher um arquivo para enviar';
    } 

}

?>

<form method='POST' enctype='multipart/form-data'>
    Arquivo: <input type='file' name='arquivo'>
    <br>
    <input type='submit' value='Enviar' name='enviar'>
</form>

O exemplo por si só é bastante explanatório. Certifique-se de que você substituiu o caminho no qual deseja salvar o arquivo, e que o usuário que está executando o php tem permissão para escrever nesse diretório.O comando move_uploaded_file é reponsável por pegar o arquivo que foi enviado, e então salva-lo no local que você especificou. Seguindo em frente então, vamos ver como fazer o envio de multiplos arquivos no mesmo formulário.
Vejamos um segundo exemplo:


<?php

if( isset( $_POST['enviar'] ) ) {

    $pathToSave '/tmp/';

    // A variavel $_FILES é uma variável do PHP, e é ela a responsável
    // por tratar arquivos que sejam enviados em um formulário
    // Nesse caso agora, a nossa variável $_FILES é um array com 3 dimensoes
    // e teremos de trata-lo, para realizar o upload dos arquivos
    // Quando é definido o nome de um campo no form html, terminado por []
    // ele é tratado como se fosse um array, e por isso podemos ter varios
    // campos com o mesmo nome
    
$i 0;
    
$msg = array( );
    
$arquivos = array( array( ) );
    foreach(  
$_FILES as $key=>$info ) {
        foreach( 
$info as $key=>$dados ) {
            for( 
$i 0$i sizeof$dados ); $i++ ) {
                
// Aqui, transformamos o array $_FILES de:
                // $_FILES["arquivo"]["name"][0]
                // $_FILES["arquivo"]["name"][1]
                // $_FILES["arquivo"]["name"][2]
                // $_FILES["arquivo"]["name"][3]
                // para
                // $arquivo[0]["name"]
                // $arquivo[1]["name"]
                // $arquivo[2]["name"]
                // $arquivo[3]["name"]
                // Dessa forma, fica mais facil trabalharmos o array depois, para salvar
                // o arquivo
                
$arquivos[$i][$key] = $info[$key][$i];
            }
        }
    }

    $i 1;

    // Fazemos o upload normalmente, igual no exemplo anterior
    
foreach( $arquivos as $file ) {

        // Verificar se o campo do arquivo foi preenchido
        
if( $file['name'] != '' ) {
            
$arquivoTmp $file['tmp_name'];
            
$arquivo $pathToSave.$file['name'];

            if( !move_uploaded_file$arquivoTmp$arquivo ) ) {
                
$msg[$i] = 'Erro no upload do arquivo '.$i;
            } else {
                
$msg[$i] = sprintf('Upload do arquivo %s foi um sucesso!',$i);
            }
        } else {
            
$msg[$i] = sprintf('O arquivo %d nao foi preenchido',$i);
        }

        $i++;
    }

    // Imprimimos as mensagens geradas pelo sistema
    
foreach( $msg as $e ) {
        
printf('%s<br>'$e);
    }

}

?>

<form method='POST' enctype='multipart/form-data'>
    Arquivo1: <input type='file' name='arquivo[]'><br>
    Arquivo2: <input type='file' name='arquivo[]'><br>
    Arquivo3: <input type='file' name='arquivo[]'><br>
    Arquivo4: <input type='file' name='arquivo[]'><br>
    <br>
    <input type='submit' value='Enviar' name='enviar'>
</form>

Veja então, que no exemplo acima, criamos um formulário, onde os campos todos tem o mesmo nome, porém são tratados como um array, por terminarem com ‘[]’. A parte mais trabalhosa é entendero array que recebemos então, e trata-lo. Depois de tratado o array, prosseguimos normalmente com o upload do arquivo.
Espero que tenha ficado claro como fazer esse upload de multiplos arquivos. Se quiser entender como a variável $_FILES é, tente utilizar a funcao var_dump nela, para ver seu conteúdo, e enteder melhor o primeiro conjunto de laços foreach que foi demonstrado no exemplo.
Caso tenha permanecido alguma duvida, afinal trabalhar com arrays de 3 ou mais dimensões é um pouco mais complicado, deixe ai um comentário, que tentarei esclarecer da melhor forma possível.

Novamente, agradeço ao leitor Rodrigo Almeida pela sugestão, e peço para que todos participem, e mandem ai suas dúvidas, críticas e sugestões.

[]s

Edit: Bom, pelo visto pode estar havendo dificuldade em copiar e colar o código dos exemplos diretamente em algum editor de texto, pois o WordPress troca as aspas simples por um tipo de aspa esquisito. Por esse motivo, enviei os códigos em formato txt.
Os links:
upload.txt – Primeiro exemplo
upload2.txt – Segundo exemplo





PHP + GD = Desenhando com PHP

19 02 2007
Bom pessoal, faz algum tempinho que estou sem escrever nada, por falta de
tempo/idéias, mas nesse momento estou sem sono, e tive uma ideia para escrever
algo, então aqui estou.
Vou falar um pouco sobre PHP e GD, e demonstrar como fazer desenhos simples
usando essa extensão do PHP.
Inicialmente você precisa ter o GD compilado e instalado em sua máquina, e
precisa compilar o php com suporte a ele, usando o parametro '--with-gd' na
linha do seu './configure'.
Para averiguar se tudo funcionou corretamente, rode o seguinte comando:

$ php -m |grep gd
gd

    
Se aparecer a palavra gd para você, está tudo correto, e podemos seguir em
frente.
Quando o ambiente está pronto para se trabalhar com GD, o primeiro passo a se
tomar, é criar uma imagem, que servirá de base para trabalharmos. De maneira a
facilitar e agilizar as coisas, irei dar um exemplo, com algumas linhas de
código e explicar o que acontece:

<?php

    // É necessário especificar o header, para informar que se trata de uma
    // imagem
    header('Content-type: image/png');

    $imagem = imagecreatetruecolor( 640, 480 );
    $vermelho = imagecolorallocate( $imagem, 255, 0, 0 );
    imagefilledrectangle( $imagem, 0, 0, 640, 480, $vermelho );

    imagepng( $imagem );
?>

Esse código, irá criar um grande retangulo vermelho.
A nossa imagem é criada na chamada da função imagecreatetruecolor, que
cria uma imagem, e retorna um resource para a mesma. Praticamente todas as
funções (se não todas) que utilizamos com GD a partir disso, farão uso desse
resource. A partir daqui, o que nos resta a fazer é desenhar a nossa imagem.
Praticamente tudo o que desenhamos na imagem utiliza cor, então para isso,
precisamos criar um resource de cor, que será utilizado pelas funções que
desenham coisas propriamente ditas. A função imagecolorallocate toma 4
parametros que lhe permitem criar uma cor. O primeiro define a imagem para qual
essa cor deve ser alocada, os seguintes definem a intensidade de vermelho, verde
e azul (RGB). Logo na sequência desenhamos um retangulo vemelho do tamanho da
imagem, utilizando a função imagefilledrectangle, que toma 6 parametros,
que definem qual a imagem em que o retangulo deve ser desenhado, qual o ponto X
inicial, o ponto Y inicial, o ponto X final, o ponto Y final e a cor do
retangulo. A função imagepng renderiza nossa imagem, e a exibe na tela.
É importante saber que o eixo de cordenadas, começa no canto superior esquerdo
da tela, ou seja, a posicão X=0, Y=0 se encontra no canto superior esquerdo de
nossa imagem. Isso pode confundir um pouco no início, mas com o passar do tempo,
a gente vai pegando o jeito.
Os desenhos, vão sendo feitos na imagem, de acordo com a sequencia em que as
chamadas para as funções são feitas, logo se eu adicionasse uma nova função no
nosso código acima para desenhar um retangulo azul, por cima do vermelho, nós
veriamos apenas o retangulo azul, e não o vermelho.
Vejamos então, algumas funções que podemos utilizar com GD, para desenharmos
coisas na nossa imagem:
    imagerectangle( resource $imagem, int $x0, int $y0, int $x1, int $y1, int
$cor )
        Desenha um retangulo na tela, sem preenchimento. Lembrando que um
quadrado nada mais é que um retangulo de lados iguais.
    imageellipse( resource $imagem, int $cx, int $cy, int $largura, int
$altura, int $cor )
        Desenha uma elipse na tela, também sem preenchimento. A elipse terá o
seu centro definido na posição $cx;$cy, terá $largura de largura e $altura de
altura. Vale lembrar também que um círculo é uma elipse que tem a mesma largura
e altura. $cor, é a cor que criamos usando imagecolorallocate.
    imagestring( resource $imagem, int $font, int $x, int $y, string $s, int
$cor )
        Desenha uma string na imagem, que começa na posição $x,$y. Se fonte for
definido como um numero entre 1 e 5, uma fonte interna do PHP é usada. $sé a
string que desejamos desenhar, e $cor, é a cor que a nossa string deverá ter.
    imagesetpixel( resource $imagem, int $x, int $y, int $cor )]
        Desenha um pixel na posição $x, $y com a cor $color.
Conhecendo essas funções já podemos fazer algumas várias coisinhas. Vejamos
abaixo então um código de exemplo, que mostra a utilização dessas funções e de
mais algumas, que deixará tudo bem claro.

<?php

    // É necessário especificar o header, para informar que se trata de uma
    // imagem
    header('Content-type: image/png');

    $imagem = imagecreatetruecolor( 640, 480 );

    // Criar algumas cores
    $vermelho = imagecolorallocate( $imagem, 255, 0, 0 );
    $verde    = imagecolorallocate( $imagem, 0, 255, 0 );
    $azul     = imagecolorallocate( $imagem, 0, 0, 255 );
    $preto    = imagecolorallocate( $imagem, 0, 0, 0 );
    $branco   = imagecolorallocate( $imagem, 255, 255, 255 );

    // Desenhar um retangulo vermelho
    imagerectangle( $imagem, 10, 100, 250, 150, $vermelho );

    // Escrever dentro do retangulo
    imagestring( $imagem, 3, 11, 120, 'Sou um retangulo sem preenchimento', $branco );

    // Desenhar um circulo azul
    imageellipse( $imagem, 100, 300, 100, 100, $azul );

    // Desenhar um quadrado verde preenchido dentro do circulo
    imagefilledrectangle( $imagem, 75, 275, 125, 325, $verde );

    // Desenhar uma linha de pixels coloridos, na vertical
    for( $i = 0; $i < 200; $i++ ) {
        imagesetpixel( $imagem, 300, $i, imagecolorallocate( $imagem, rand(0,255),rand(0,255),rand(0,255) ) );
    }

    // Desenhar um circulo preenchido verde
    imagefilledellipse( $imagem, 400, 300, 100, 100, $verde );

    imagepng($imagem);

?>

Bem, temos uma imagem com alguns desenhos, porém uma coisa ainda incomoda, e
essa coisa é a cor de fundo. Como mudar a cor de fundo? Basta usar a função
imagefill, que preenche uma determinada area com a cor especificada.
Podemos utilizar essa função para pintarmos apenas a parte interna do nosso
retangulo ou circulo que nao tem preenchimento. Vamos então a um ultimo exemplo
que usa essa função.

<?php

    // É necessário especificar o header, para informar que se trata de uma
    // imagem
    header('Content-type: image/png');

    $imagem = imagecreatetruecolor( 640, 480 );

    // Criar algumas cores
    $vermelho = imagecolorallocate( $imagem, 255, 0, 0 );
    $verde    = imagecolorallocate( $imagem, 0, 255, 0 );
    $azul     = imagecolorallocate( $imagem, 0, 0, 255 );
    $preto    = imagecolorallocate( $imagem, 0, 0, 0 );
    $branco   = imagecolorallocate( $imagem, 255, 255, 255 );

    // pintar o fundo de branco
    imagefill( $imagem, 0, 0, $branco );

    // Desenhar um retangulo vermelho
    imagerectangle( $imagem, 10, 100, 250, 150, $vermelho );

    // Pintar o retangulo de azul
    // 11 e 101, é uma posição dentro do retangulo
    imagefill( $imagem, 11, 101, $azul );

    imagepng($imagem);

?>

Temos ai então uma imagem branca, com um retangulo azul de borda vermelha.
Estamos sempre usando a função imagepng, mas existem outras, para criar a
imagem nos formatos gif e jpg por exemplo, sendo elas:
    imagejpeg
    imagegif

Bom, por hoje é isso. Espero que esse texto possa ter dado uma breve introdução
a extensão GD, e possa te ajudar com alguns problemas, como criação de captchas,
gráficos, e qualquer outra coisa mais que lhe possa ser util (Eu tinha umas
outras ideias, mas sao 3 da manha, e eu ralmente esqueci).
Para maiores informações e mais funções, consulte:
http://php.net/gd

[]s