Dicas para desenvolvimento de extensão em PHP

23 03 2007

É, não é complicado…

Pra quem já começou ou pretende começar, segue 4 ótimos links:

Extension Writing Part I: Introduction to PHP and Zend
Introdução, falando desde o mais básico da criação de uma extensão.

PHP and Zend Engine Internamente
Seção no manual do PHP com bastente informação sobre APIs

Extending and Embedding PHP
Livro da mesma autora do primeiro artigo (Sara Golemon). É o típico livro “must have”.

PHP Cross Reference
Fonte “navegavel” do PHP. A forma mais fácil de compreender o que se passa internamente, é lendo o fonte enquanto se desenvolve, ver o que é cada macro ( há centenas de macros ), entender cada struct, e por aí vai.

Com apenas estes quatro links, acredito ser possível desenvolver bastante coisa interessante.





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





espeak-php / SSML

22 03 2007

Mexendo na extensão hoje acabei por testar o uso de SSML . Interessante:


<?php
// ssml.php
$xml =<<<eoc
<speak version=”1.0″ xmlns=”http://www.w3.org/2001/10/synthesis”
    xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
    xsi:schemaLocation=”http://www.w3.org/TR/speech-synthesis/synthesis.xsd”
    xml:lang=”en-US”>

    <voice gender=”female” age=”22″>
        <p>Hello world! </p>
    </voice>
                                                  
    <voice gender=”male” age=”30″>
        <p>Hello world!</p>
    </voice>
    <voice xml:lang=”pt” gender=”male”>
        <p>Olá mundo!</p>
    </voice>
</speak>
eoc;

dl(‘espeak.so’);

espeak_initialize(ESPEAK_AUDIO_OUTPUT_PLAYBACK0);
espeak_SetVoiceByName(“en”);
espeak_synth($xmlstrlen($xml), 0ESPEAK_POS_CHARACTER0ESPEAK_SSML0);
espeak_synchronize();
espeak_terminate();

As vozes não são as mais bonitas do mundo, mas também não são as piores. Acho que nos próximos dias consigo implementar todas as funções disponibilizadas pela lib do espeak. Está no svn do projeto.





Notícias e links: 21/03

21 03 2007

CSS+Javascript power. Fancy menu
Não é PHP, mas vai dizer que nunca precisou de um menu pra alguma aplicação ? Este menu é bem estiloso.

What separates a professional PHP web developer from a scripter?

Quebec Slides
Slides de duas apresentações: Securing PHP Applications e Migrating to PHP 5.2.1
O primeiro contém dezenas de dicas de como aumentar a segurança de uma aplicação em PHP e a segunda fornece diversos motivos para se migrar para php 5.2. Vale o tempo investido.

Object Interaction and Mediator Classes in PHP 5
Abstracting Database Access Using Polymorphism with Objects in PHP 5
Mais artigos sobre design patterns do devshed. O interessante nestes artigos (a grande maioria ) é que realmente falam sobre o pattern e onde / como utilizar, o que faz com que eles sejam úteis não somente enquanto se desenvolve em PHP, mas em qualquer linguagem.

CodeIgniter vs. CakePHP
Comparativo entre CodeIgniter e CakePHP. Não da pra tirar muitas conclusões sobre qual é o melhor ( se é que algum é melhor que outro, no geral ), mas é possível conhecer algumas features de cada um deles.

XML for PHP developers, Part 3: Advanced techniques to read, manipulate, and write XML
Terceira parte do artigo sobre XML para desenvolvedores PHP. Não lembro se postei a segunda, então segue ( e a primeira também:
XML for PHP developers, Part 2: Advanced XML parsing techniques
XML for PHP developers, Part 1: The 15-minute PHP-with-XML starter

Command-line PHP? Yes, you can!
Breve introdução ao uso de PHP em linha de comando. É, muita gente utiliza PHP apenas como uma linguagem voltada à web, embora muitos já a considerem (eu estou entre estes muitos) uma linguagem de uso geral.
PHP em console + ncurses é bastante simples e interessante de se usar:

r2s

Tão eficiente quanto uma interface web : )





php-dev

21 03 2007

Na lista de discussão php-dev sempre há mensagens interessantes.

Nesta última semana vem sendo discutido um projeto para o GSoC , o dbobj. Trata-se de uma (não é apenas mais uma ) implementação nativa (isso é, uma extensão para PHP, e não escrito em PHP ) de ORM. Foi descrito com maiores detalhes em um email que pode ser visto no histórico da lista.

Poderia ser bastante interessante se “pegasse”, criaria uma certa padronização na forma de acesso a dados. Mas é bem provável que quem já utiliza algum framework para isso não o abandonaria. Enfim, não ha nada a perder com isso. O projeto phpaspect também “nasceu” no GSoC (outra “edição”). Deve dar bons frutos também.

Um outro assunto que vem sendo discutido ( e muito discutido ) é a implementação de funções anônimas em PHP. Um patch foi enviado e demonstrava o funcionamento desta implementação ( por sinal, o código foi esse:

$data = array(“zoo”, “orange”, “car”, “lemon”, “apple”);
usort($data, function($a, $b) { return strcmp($a, $b); });

)

Entre outras coisas, foi comentado também sobre uma possível implementação de closures em PHP. Nunca precisei, nem de funções anônimas, mas sei lá, vai que um dia eu precise : )

Então fica a dica, a lista pode ser assinada por qualquer um. Apenas se prepare para receber muitas mensagens diariamente.





Dica rápida: Verificar protótipos de funções PHP rapidamente

19 03 2007

Tenho plena certeza que não sou o único que sempre tem dúvidas com a ordem de determinadas funções em php, principalmente as funções de manipulação de array e de strings. A culpa não é minha, não há um padrão naquilo. E isso é uma das poucas coisas que me “irritam” enquanto estou desenvolvendo.

Quando tenho alguma dúvida ( várias vezes por dia, tenho uma “excelente” memória ) costumo consultar a documentação em php.net, seguido pelo nome da função:

http://php.net/array_search, http://php.net/substr, e por ai vai…

Até tenho documentação instalada localmente, mas é bastante chato ficar procurando. É mais prático olhar direto no site.

Mas hoje, tive a brilhante idéia de começar a utilizar o próprio php ( cli ) pra exibir o protótipo das funções, que me poupa algum tempo e achei bastante útil. Acho que pode ser útil para quem tem esse mesmo problema que eu. Veja a simplicidade:

$ php –rf substr
Function [ public function substr ] {

- Parameters [3] {
Parameter #0 [ $str ]
Parameter #1 [ $start ]
Parameter #2 [ $length ]
}
}

$ php –rf array_search
Function [ public function array_search ] {

- Parameters [3] {
Parameter #0 [ $needle ]
Parameter #1 [ $haystack ]
Parameter #2 [ $strict ]
}
}

$ php –rf array_key_exists
Function [ public function array_key_exists ] {

- Parameters [2] {
Parameter #0 [ $key ]
Parameter #1 [ $search ]
}
}

Muito bom!!! Espero encontrar mais alguma utilidade nisso : D





Notícias e links – 06/03

16 03 2007

Bastante ocupado ultimamente … :|

Using Zend Framework components in Code Igniter
Dica de como utilizar componentes do ZF no CI. Sei lá, vai que alguém precise

Zend Certification: Self Test
Pensando em se certifar como ZCE ? Que tal um teste antes ?
Oito questões, com algumas “pegadinhas”

Introducing Mediator Classes in PHP 5
Working with Strings and the Composite Pattern in PHP 5
Mais dois artigos da série de design patterns em PHP

Nine examples on how NOT to hire a PHP developer
Fica a dica para quem eventualmente tiver que contratar um programador ( não somente PHP )

Tutorial: Getting Started with the Zend Framework
Pequeno tutorial (19 páginas) com um introdução ao Zend Framework. Nunca usou um framework ? Que tal começar com a usar com ajuda deste tutorial.

Continuous integration with PHP
Breve introdução sobre integração contínua durante o desenvolvimento em PHP, com algumas dicas sobre PHPUnit e Phing.

Simulando Sobrecarga de Métodos no PHP
http://www.imasters.com.br/artigo/5350/php/simulando_sobrecarga_de_metodos_no_php/

Quercus
PHP in GlassFish, first steps
MediaWiki on GlassFish — via Quercus
Caucho Resin adds PHP
Nos últimos dias muito tem se falado sobre integração PHP / Java, ganho de performance e blablabla…

Would PHP benefit from JIT compilation?





espeak-php: v0.1 alpha

13 03 2007

Criei o projeto no sourceforge e enviei algumas informações para lá.

O “site” do projeto pode ser visto aqui. O site, por algum motivo obscuro, não está funcionando corretamente (as vezes funciona, as vezes não), mas já da pra ver como instalar e alguns exemplos de uso. Nos próximos dias escrevo uma documentação decente…

Para interessados, o repositório subversion do projeto esta em https://espeak-php.svn.sourceforge.net/svnroot/espeak-php/trunk e há um pacote disponível aqui





php + text to speech

12 03 2007

Estava lendo RSS hoje e por acaso vi este post, onde o autor escreveu um pequeno programa em C# para ler RSSs. Achei interessante, afinal, acompanho diversos sites e blogs via rss.

A aplicacação que ele fez funciona somente em windows, visto que faz uso da “Microsoft Speech API”.

Anteriormente havia criado um script bem simples, que utilizava o festival para sintetização de voz, utilizando system(). Funcionava sem muitos problemas…

Ai pensei hoje em fazer um leitor de RSS no mesmo molde do citado acima, mas utilizando um outro sintetizador de voz, o espeak. A resultado final que se ouve é comparável ao do festival, e é relativamente mais simples instalar o espeak. E além disso, ele possui uma biblioteca compartilhada de uso bastante simples (não sei se a do festival é simples também), o que facilita o desenvolvimento de aplicações em C.

A idéia era criar uma extensão para o PHP que fizesse uso dessa biblioteca, para utilizar as funções nativamente em um script, e não usando system().

Depois de algumas horas escrevendo código, eis que tenho uma versão alpha e funcional (e com bugs, claro) da extensão. Ficou bem mais interessante utilizar tts agora. E o leitor de rss ficou bem simples, é basicamente isso:


<?php
dl
(‘espeak.so’);
$feeds simplexml_load_file (‘http://rss.terra.com.br/0,,EI4795,00.xml’)->channel->item;
espeak_initialize(ESPEAK_AUDIO_OUTPUT_PLAYBACK0);
espeak_setVoiceByName(“pt”);
espeak_setParameter(ESPEAK_VOLUME900);
foreach ( 
$feeds as $f ) {
    
espeak_synth($f->titlestrlen($f->title), 0ESPEAK_POS_CHARACTER000);
    
espeak_synchronize();
    
sleep(1);
}
espeak_terminate();
?>

Bem simples, assim como mostrado em um outro post, não é necessário muito código para obter uma lista de notícias de um feed.

Não é a primeira extensão que escrevo, mas é a primeira que estarei publicando… Enviei hoje a requisição de aprovação no sourceforge e acredito que até terça-feira já posso estar enviando o primeiro commit no repositório.

Pensei em enviar para o PECL, mas devido ao fato de o espeak utilizar licença GPL, o projeto não poderia ser enviado para lá, “incompatibilidade” de licenças…

Breve envio mais informações sobre o projeto.





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 www.belgium.be
    www.belgium.be has address 193.191.209.193
    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.





mysql to xml: Como transformar um resultado de uma query para XML ( de forma simples )

7 03 2007

Para que ? não sei!
Mas talvez já tenha precisado disso. Então segue.

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 MYSQL2XML;

-- selecionamos o banco de dados
USE MYSQL2XML;

-- 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;

-- adicionamos alguns registros
INSERT INTO exemplo VALUES ('', 'Primeiro exemplo');
INSERT INTO exemplo VALUES ('', 'Segundo exemplo');
INSERT INTO exemplo VALUES ('', 'Terceiro exemplo');

E o script PHP para transformar o resultado da query sql para formato XML é o qual segue. Está todo comentado, para facilitar o entendimento.


<?php
    
// arquivo mysql2xml.php

    // definimos informacoes para conexao ao banco de dados:
    $banco   ‘mysql2xml’;             // nome do banco
    
$host    ‘localhost’;             // host
    
$usuario ‘root’;                  // usuario
    
$senha   ”       ;               // senha
    
$sql     ’select * from exemplo’// query a ser executada
    
    
    // criamos um objeto do tipo SimpleXMLElement, o qual ira
    // gerar o XML para nos
    
$sxe = new SimpleXMLElement(‘<resultset />’);
    
    
// connectamos ao host e executamos a query sql
    
mysql_connect($host$usuario$senha);
    
mysql_select_db($banco);
    
$rs mysql_query($sql);
    
    
// em um loop, obtemos todas as linhas do resultado
    // da query. Note que o resultado e’ obtido como um array
    // associativo apenas.
    
while ( $row mysql_fetch_array($rsMYSQL_ASSOC) ) {
        
// abaixo do primeiro node do XML que estamos criando, vamos
        // adicionando mais um no, que ira conter o resultado da query.
        // na primeira iteracao do loop, o xml estaria parecendo com
        //
        // <resultset>
        //     <line></line>
        // </resultset>
        
$line $sxe->addChild(‘line’);

        // e, em mais um loop, passamos por todos as colunas
        // do resultado da query e adicionamos cada uma delas
        // ao node criado anteriomente. Neste loop, apos a primeira
        // e a segunda iteraca, o xml estaria parecendo com: 
        // (para o sql citado anteriormente)
        //
        // <resultset>
        //     <line>
        //         <id_exemplo>1</id_exemplo>
        //         <descricao>Primeiro exemplo</descricao> 
        //     </line>
        // </resultset>
        
foreach ( $row as $fieldName => $value )
            
$line->addChild($fieldName$value);
    }
    
    
// finalmente, transformamos o objeto SimpleXMLElement criado no 
    // inicio do scrip em uma string formatada em XML
    
echo $sxe->asXML();
?> 

Executando em linha de comando, temos (o resultado é exibido em uma linha apenas, formatei para propósito de visualização) :

$ php mysql2xml.php

<?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>

Arquivos:
mysql2xml.php
exemplo.sql

É isso.





Notícias e links – 07/03

7 03 2007

Pear releases
PEAR 1.5.1
pearweb_phars 1.2.0
PHP_ParserGenerator 0.1.5
PHP_Parser_DocblockParser 0.1.0
PHP_Parser 0.2.0
pearweb 1.9.5
Validate_LV 1.0.0RC1

Pecl releases
timezonedb 2007.3
ingres 1.4.3

February Issue (02.2007) of International PHP Magazine Released
Edição de fevereiro da International PHP Magazine. Contém um artigo falando sobre refactoring, coisa que não é muito encontrada ( sobre php ) na internet.

Programming:PHP
wikibook sobre PHP. Contém bastante material interessante, além de dezenas de links.

Edição 02 – Março 2007
Segunda edição da PHP Magazine, revista nacional sobre PHP.
Conta com 8 artigos distribuídos em 48 páginas.

Introducing the Composite Pattern in PHP 5
Introdução ao design pattern composite.
Artigo dividido em 4 partes, tem desde uma introdução a exemplos de uso deste pattern.





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’$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.





Notícias e links – 02/03

2 03 2007

Pear releases
Image_Barcode 1.1.0
XML_RPC2 1.0.1
Text_Wiki_Creole 0.5.0

Zend Framework Gets An Unofficial PEAR Channel
Para quem gosta de utilizar PEAR para instalar componentes PHP e outras coisas, o Zend Framework pode agora também ser instalado por ele.

the Month of PHP Bugs
E foi dada a largada! Até o presente momento 5 novos bugs foram demonstrados. Está indo bem, uma média de 2.5 ao dia…

PHP 4.4.6 Release Announcement
Novo release de PHP. Diversas correções de bugs e atualização da PCRE.

International PHP Conference 2007 – the hotspot of the PHP community
Alguns temas interessantes serão discutidos. E se fizer inscrição até 15/03 você ainda ganha um iPod Shuffle! Sensacional!!! ( imagine o preço )

What the Web’s most popular sites are running on
O que acha que é ?