Dica rápida: printf(“{0} {1} {0} “, ‘foo’, ‘bar’);

14 12 2007

Ok, não é bem isso, mas é quase. Segue a conversa:

<anmsx> printf("ola {0}, hoje é {1}. Ja disse seu nome, {0} ? ", ‘anmsx’, ‘domingo’);
<anmsx> queria algo assim no php
<anmsx> tipo q tem no c#
<ecl> ahhaha
<anmsx> sacou a ideia ?
<ecl> sim
<anmsx> da pra fazer em codigo mesmo
<ecl> mas da pra fazer isso atualmente com o recurso atual tambem, ta ligado?
<anmsx> si
<ecl> hahah, falei cheio de redundancia
<anmsx> func_get_args ou coisa assim, nao ?
<ecl> anmsx: falo no printf mesmo
<anmsx> ah é ?
<anmsx> como ?
<anmsx> isso eu nao sei
<ecl> %[numero do arg]$[tipo]
<anmsx> 5.3 ?
<ecl> nao
<ecl> antigo.
<anmsx> xover
<ecl> de qualquer forma, usando o {N} para string, seria legal
<anmsx> certeza q é dessa forma q colocou ?
<anmsx> onde tem isso na doc ?
<anmsx> nao funcionou
<anmsx> $ php -r ‘echo printf("Ola %1\$s hoje é %2\$s, certo %1\$s ?", "anmsx", "domingo");’
<anmsx> Ola anmsx hoje é domingo, certo anmsx ?
<anmsx> cool





Link: Dezenas de slides

22 11 2007




PHP / CruiseControl

19 11 2007




PHP / refactoring: Como ? (Outra vez)

22 09 2007

Já havia  comentado aqui alguma coisa. Mas aqui encontramos um artigo muito legal sobre isso.

Apesar de não ser permitido, muitos beta-testers (e desenvolvedores) dessa “next generation IDE” tem comentado sobre as features da nova IDE da Zend. Também gostaria de falar sobre profiling, code coverage em testes unitários, debug e blablabla, mas não posso :) .





A importância da comunicação

27 07 2007

Mais um off-topic

falta_comunicao_desenvolvimento.jpg

Comunicação é uma das premissas do Extreme Programing que acredito ser a mais importante.

Esta imagem é muito utilizada, chega a ser um chavão para os “mais andados”. Vi ela 3 vezes neste mês e aproveitei para compartilhar, sempre tem gente que não a viu.
Aproveitando o off-topic, fica uma sugestão:

Haverá hoje uma apresentação sobre Scrum (o título é “Entendendo Scrum Para Gerenciar Projetos Ágeis” ):

http://www.egenial.com.br/betaEventos

A primeira apresentação que assisti neste ambiente foi exatamente uma “introdução” a XP, excelente por sinal
. É bem provável que a qualidade se mantenha, então fica a sugestão, se não tem alguma coisa suficientemente importante para fazer, vale a pena assistir, hoje, a partir das 20:30. Estarei por lá.

E parabéns aos que vem fazendo com que estas apresentações aconteçam (Carlos Eduardo & cia)





Visão Ágil – Revista Brasileira Sobre Processos Ágeis

24 07 2007

Visão Ágil é primeira revista brasileira dedicada a processos ágeis, seu principal objetivo, é fornecer um canal único e dinâmico para reunir todas das vertentes ativas no cenário nacional.Este espaço, é aberto a todas as tribos como: Extreme Programming, FDD, Scrum e outras técnicas ágeis correlacionadas.

Portanto, acesse a primeira edição desse projeto ousado e feito com muito carinho para todos os agilistas do Brasil.

Conteúdo muito interessante.
Para quem não segue nenhum processo de desenvolvimento de software ou segue algum dito “burocrático”, e tem vontade de conhecer algum processo “ágil”, vale uma lida.

Entre os artigos, podemos ler sobre XP, SCRUM, um artigo falando sobre “As Cinco Doenças do Gerenciamento de Projetos” e um sobre “Contrato de Escopo Negociável”.

Apesar de não se aprofundar muito nos assuntos, todos os artigos tem um conteúdo muito bom.

Veja mais em visaoagil.com





Annotations (@QualquerCoisa) em PHP

15 07 2007

Havia lido algum tempo atrás sobre annotations em PHP, mas nada muito concreto.

Vi hoje uma apresentação (antiga, do phpconference) falando mais sobre isso:

Mais, aqui
Muito interessante, bem que poderia fazer parte do core do PHP





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





PHP / refactoring: Como ? (Parte 2)

25 05 2007

Pois é, eu não sabia que teria parte 2, mas este é para ser uma continuação do post PHP / refactoring: Como ?.

Vejamos agora como modificar o nome de uma função e as chamadas para a mesma. O exemplo anterior com algumas modificações será utilizado:


<?php
// arquivo sample2.php

$foo   ‘foo’;
$hello “Ola $foo\n”;

// funcao foo() no comentario nao sera modificada

function foo()
{
    
// variavel $foo nao sera modificada
    
$foo “dentro de foo()\n”;
    echo 
$foo;
}

// exibimos $hello
echo $hello;

// observe que foo() e foo () sao diferentes: 
// foo() equivale a:
//      T_STRING        (foo)
//      (               (abre parenteses)
//
// enquanto foo () equivale a:
//      T_STRING        (foo)
//      T_WHITESPACE    (‘ ’)
//      (               (abre parenteses)
//
// e por esse motivo deve ser tratado como diferente
foo ( );
?>

E a função com exemplo de uso:


<?php
// arquivo change_function_name.php

/**
 * Funcao que ira modificar o nome de uma funcao
 *
 * @param  array  $tokens  Array com os tokens a serem analisados
 * @param  string $oldName Nome da funcao que sera modificada
 * @param  string $newName Novo nome da funcao
 * @return string Codigo-fonte referente aos tokens fornecidos, com a 
 * funcao devidamente modificada
 */
function changeFunctionName($tokens$oldName$newName)
{
    
// variavel que ira conter o codigo-fonte a ser retornado
    
$ret ;

    // contador, marcara o indice do token em uso
    
$tokenIndex = -1;
    
    
// como $tokens e’ um array, utilizamos foreach para
    // passar por todos os seus itens
    
foreach ($tokens as $token) {
        
$tokenIndex++;
        
// quando se obtem os tokens de um arquivo, eles vem em um 
        // array contendo o numero do token e o valor ou em uma string,
        // contendo apenas o valor. Entao verificamos qual o caso.
        
if (!is_array($token)) {
            
$tokenName  false;
            
$tokenValue $token;
        } else {
            
$tokenName  token_name($token[0]);
            
$tokenValue $token[1];
        }

        // verificamos se o token atual pode ser considerado uma funcao
        
if ($tokenName == ‘T_STRING’) {
            
// obtemos os dois proximos tokens
            
$nextToken  $tokens[$tokenIndex 1];
            
$nnextToken $tokens[$tokenIndex 2];

            // aqui temos o seguinte:
            // se o proximo token for igual a ”(“ E se o valor do token atual for igual
            // ao nome da funcao que queremos modificar…
            
$flag  = ($nextToken[0] == ‘(‘ && $tokenValue == $oldName);
            
            
// … OU o proximo token for um espaco E o token apos o proximo for igual a ”(“
            // E o valor do token atual for igual ao nome da funcao que queremos modificar…
            
$flag |= (@token_name($nextToken[0]) == ‘T_WHITESPACE’ && $nnextToken[0] == ‘(‘ && $tokenValue == $oldName);

            // … entao modificamos o valor do token,
            
if ($flag) {
                
$tokenValue $newName;
                
$ret .= $tokenValue;
                continue;
            }
        }
        
        
// se chegou ate aqui, significa que nao e’ um token que nos interessa, apenas pegamos
        // o valor do token e o adicionamos ao final do fonte a ser retornado
        
$ret .= $tokenValue;
    }
    
    
// retornamos o fonte
    
return $ret;
}

// exemplo de uso da funcao

// obtemos o conteudo do arquivo que iremos modificar
$arquivo file_get_contents(’sample2.php’);

// e utilizamos a funcao token_get_all para obter todos
// os tokens do arquivo. Observe que tudo no script e’
// tratado como sendo um token
$tokens  token_get_all($arquivo);

// modificamos foo() para bar()
$bla changeFunctionName($tokens‘foo’‘bar’);

echo $bla;

?>

Executando:

$ php change_function_name.php
<?php
// arquivo sample2.php

$foo = ‘foo’;
$hello = "Ola $foo\n";

// funcao foo() no comentario nao sera modificada

function bar()
{
// variavel $foo nao sera modificada
$foo = "dentro de foo()\n";
echo $foo;
}

// exibimos $hello
echo $hello;

// observe que foo() e foo () sao diferentes:
// foo() equivale a:
// T_STRING (foo)
// ( (abre parenteses)
//
// enquanto foo () equivale a:
// T_STRING (foo)
// T_WHITESPACE (‘ ‘)
// ( (abre parenteses)
//
// e por esse motivo deve ser tratado como diferente
bar ( );
?>

Observe que a declaração da função foi modificada ( function bar ) e a chamada à função também foi modificada (bar ( ); ).
Ótimo, esta pronto ? Não…

Como bem sabemos, é possível executar funções de outras formas em PHP, como por exemplo, utilizando call_user_func, eval, variáveis utilizadas como funções ( $foo(); ), funções utilizadas como callback, …

Então, em uma implementação completa desta função, deveriamos nos atentar a estes fatos.
Para alguns casos, seria relativamente fácil criar uma implementação:
- Em eval, poderiamos utilizar a string que esta sendo executada e, recursivamente, chamar a função changeFunctionName para os tokens obtidos para esta string
- Em call_user_func / call_user_func_array, poderiamos verificar se o token atual é um T_STRING e o valor do token é ‘call_user_func’, desta forma. Se for, analisaria-se os tokens seguintes para ver se não teria relação com a função sendo renomeada;

Já em outros casos, seria necessário um pouco mais de malabarismos:
- Em variáveis utilizadas como funções, provavelmente precisariamos de um trackback das variáveis, para verificar se o valor dela não corresponde ao nome da função que desejamos renomear
- Utilizar um grande switch para verificar todas as funções builtin do PHP que utilizam funções como callback

De qualquer forma, para fontes onde não se utilize a função sendo renomeada de forma mais “avançada”, este exemplo deve funcionar.

change_var_name.php (exemplo anterior)
change_function_name.php





Link: Comparação de IDES para desenvolvimento em PHP

5 05 2007

É um post antigo, mas bem interessante, onde é feita uma comparação entre Eclipse, Komodo, PHP Designer, PhpED, PHPEdit e Zend Studio:

Seven great PHP IDEs compared

Tinha idéia de escrever um post parecido, comparando também (se é que alguns desses podem ser comparados) o jdeveloper da oracle, com “Oracle PHP Extension for Oracle JDeveloper 10g”, o delphi4php, o pdt, o quanta, o kate, o kdevelop, o dreamweaver, o vim e o mcedit (este por ser o editor que uso atualmente : ) ).

Além desses, há outra dezena que poderia entrar na comparação / descrição, mas por não ter muito tempo pra isso, acho que vale a dica da comparação do link.





PHP / refactoring: Como ?

15 04 2007

Refatorar código em PHP normalmente não é simples.

As IDEs que mais utilizei até hoje, como pdt (aka eclipse + plugins), zend studio e quanta plus não oferecem (ou não ofereciam na época) suporte a nenhum tipo de refatoração. Nada de renomear variável, função, classe, método.

Talvez a maior dificuldade em se trabalhar com com isso seja a tipagem fraca do PHP (somente talvez). Mas alguns trabalhos encontrados na internet, como por exemplo o phc – php compiler (não se deixe enganar pelo nome), podem ajudar: Há aqui um exemplo de como modificar chamadas de uma função para outra. Bastante trabalho para uma tarefa relativamente simples; O phc transforma o código php em uma AST – Abstract Syntax Tree e o exemplo atravessa essa árvore efetuando as modificações.

Algumas classes implementadas em PHP mesmo também são encontradas no PEAR. Mas também não há nada que seja muito utilizável.

Acredito que o que se tenha de mais “útil” no momento são as funções da extensão tokenizer (que é compilada por padrão). Com ela podemos trabalhar mais facilmente com um script, para criarmos algum tipo de ferramenta útil para refatoração. Vejamos por exemplo, como criar uma função para modificar o nome de uma variável:


<?php
// arquivo sample.php

$foo   ‘foo’;
$hello “Ola $foo\n”;

// variavel $foo no comentario nao sera modificada

function foo()
{
    
// variavel $foo neste contexto sera modificada
    
$foo ‘1′;
    echo 
$foo;
}
    
echo 
$hello;
?>


<?php
// arquivo change_var_name.php

/**
 * Funcao que ira modificar o nome de uma variavel
 *
 * @param  array  $tokens  Array com os tokens a serem analisados
 * @param  string $oldName Nome da variavel que sera modificada
 * @param  string $newName Novo nome da variavel
 * @return string Codigo-fonte referente aos tokens fornecidos, com a 
 * variavel devidamente modificada
 */
function changeVarName($tokens$oldName$newName)
{
    
// variavel que ira conter o codigo-fonte a ser retornado
    
$ret ;
    
    
// como $tokens e’ um array, utilizamos foreach para
    // passar por todos os seus itens
    
foreach ($tokens as $token) {
    
        
// quando se obtem os tokens de um arquivo, eles vem em um 
        // array contendo o numero do token e o valor ou em uma string,
        // contendo apenas o valor. Entao verificamos qual o caso.
        
if (!is_array($token)) {
            
$tokenName  false;
            
$tokenValue $token;
        } else {
            
$tokenName  token_name($token[0]);
            
$tokenValue $token[1];
        }

        // se nao ha o nome/numero do token, siginifica que ele nao e’ uma variavel,
        // pois elas contem o numero e o valor. Entao podemos adicionar o token ao
        // codigo-fonte que sera retornado e passar para o proximo token
        
if (!$tokenName) {
            
$ret .= $tokenValue;
            continue;
        }        
        
        
// verificamos se o token e’ uma variavel - T_VARIABLE. Se nao for, adicionamos
        // o valor do token ao codigo-fonte que sera retornado e passar para o proximo token
        
if ($tokenName != ‘T_VARIABLE’) {
            
$ret .= $tokenValue;
            continue;
        }

        // verificamos se o valor do token, ou seja, o nome da variavel, e’ o mesmo
        // que queremos modificar. Se nao for, o processo e’ o mesmo do anterior, adicionamos
        // o valor ao codigo-fonte e passamos para o proximo token
        
if ($tokenValue != $oldName) {
            
$ret .= $tokenValue;
            continue;
        }

        // se chegou ate aqui, significa que o token e’ uma variavel e tem o nome que
        // precisa ser modificado. Entao modificamos o valor do token e o adicionamos ao
        // codigo-fonte que sera retornado
        
        
$tokenValue $newName;
        
$ret .= $tokenValue;
    }
    
    
// retornamos o fonte
    
return $ret;
}

// exemplo de uso da funcao

// obtemos o conteudo do arquivo que iremos modificar
$arquivo file_get_contents(’sample.php’);

// e utilizamos a funcao token_get_all para obter todos
// os tokens do arquivo. Observe que tudo no script e’
// tratado como sendo um token
$tokens  token_get_all($arquivo);

// modificamos $foo para $bar
$bla changeVarName($tokens‘$foo’‘$bar’);

echo $bla;

E, executando:

$ php change_var_name.php
<?php
// arquivo sample.php

$bar = ‘foo’;
$hello = "Ola $bar\n";

// variavel $foo no comentario nao sera modificada

function foo()
{
// variavel $foo neste contexto sera modificada
$bar = ‘1′;
echo $bar;
}

echo $hello;
?>

Exemplo bem simples de como poderiamos utilizar tokenizer para refatorar código. Observe que o nome da variável foi modificada tanto no contexto global, quanto no contexto da função “foo”. Alguns outros detalhes poderiam ser observados, mas quem sabe em um post futuro.

É bem possível (e acho que relativamente fácil) trabalhar melhor neste exemplo para se definir onde se deseja modificar a variável. E quem sabe nos próximos dias escrever uma classe para refatorar realmente, permitindo modificar nome funções, classes e outras coisas úteis.

E para quem não sabe o que é refatoração, vale uma lida no artigo da wikipedia e em Refactoring Home Page.





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





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.