PHP-GTK no Lion

Desde que comprei o MacBook, não consegui mais trabalhar com PHP-GTK, pois não teve jeito de conseguir compilar a extensão.

Tentei os mais diversos tutoriais e commits do SVN, tentei achar pacotes pré-compilados que funcionassem com o PHP original do Lion (versão 5.3.15) e nada, então, como o tempo já é escasso e eu desorganizado com a agenda, acabei deixando de lado.

Mas esses dias, conversando com o Pablo Dall’Oglio, que fiquei sabendo por acaso que também tinha um MacBook, resolvi perguntar se ele tinha alguma receita para me passar. E eis que melhor ainda, ele já me indicou o ambiente compilado, pronto para uso, e que não modifica em nada o seu PHP original - exatamente o que eu queria.

O link para baixar é http://www.adianti.com.br/studio-mac, funcionou perfeito no Lion, basta executar o pkg e pronto, depois é só testar digitando php-gtk2 no terminal.

Valeu Pablo!


Brincando com YQL - Yahoo Query Language

A tempos ouvi falar da YQL - ou Yahoo Query Language -, uma linguagem SQL criada pelo Yahoo, que nos permite consultar, filtrar e juntar dados através de web services.

Você pode por exemplo, filtrar dados de uma página html ou de um xml conforme sua necessidade, usando a já conhecida por nós, SQL, e outros recursos, como XPath.

A YQL nos permite também consultar bases de dados públicas, de serviços já conhecidos por todos nós, como o próprio Yahoo, Twitter, Flickr, YouTube entre outros.  

Assim, você pode reunir todos os serviços que sua aplicação irá consumir, em um único local, utilizando uma única API.

Eu procurei por aí, e não achei muita coisa interessante sendo desenvolvida, infelizmente. Acredito que por não ser tão conhecida da comunidade, ninguém parou para pensar nas inúmeras possibilidades que esse serviço pode oferecer.

Mas, falando tanto assim, vamos a parte prática ;)

SPara mostrar um exemplo rodando, vamos executar este YQL, onde listo todos os links da página inicial do Globo.com:

> select * from html where url="http://www.globo.com" and xpath='//a'

Agora selecione abaixo da box de edição, o tipo de retorno que deseja e pronto, super maneiro não é? Tá, mas agora você deve estar se perguntando, como utilizar isso de forma prática, vou colar um exemplo utilizando jQuery:

    $.ajax({
    type:'GET',
    url: "http://y.ahoo.it/jydbv",
    dataType: 'jsonp',
    crossDomain: true,
    beforeSend: function(){
        console.log('enviando requisição');
    },
    success:function(feed){
        if (feed.query.count > 0) {
            var results = feed.query.results.a;

            results.each(function(indice, objeto) {
                console.log(objeto);
            });
        } else {
            console.log('sem resultados.);
        }
    }
});

Explicando: o jQuery nos permite chamar um JSON “paralelo”, ou seja, em outro host, e é isso que o retorno do Yahoo nos envia, por isso que definimos ali na chamada, o dataType como ‘jsonp’, isso é muito importante. Depois disso, é só navegar no retorno, bem simples ;)

Em tempo, a url ali informada, ela pode ser obtida pelo console, no campo ao rodapé, intitulado “The Rest Query”, ou o topo, em um link bem discreto situado sobre a caixa de edição de Query, intitulado ‘permalink’, onde você pode recuperar o link inteiro, ou de forma diminuta, como a que eu utilizei. Se você colar este link no seu navegador, irá obter o retorno que configurou (XLM/JSON) no console, ou no parâmetro ‘format’ da URL.

Divirta-se ;)


Daemons em PHP

Quem nunca precisou criar um script que tivesse que rodar de tempos em tempos para efetuar alguma tarefa não é mesmo? Geralmente usamos a Cron para rodarmos os scripts, mas e quando o script já não roda mais no mesmo tempo esperado, e quando olhamos, temos várias instancias do mesmo script rodando no servidor, bem chato isso.

Eu sei que você vai falar: ‘sim, mas podemos tratar isso via não sei que’, sim eu sei., mas porque não, deixarmos um script rodando “eternamente” e executando a tarefa exatamente no momento exato em que um upload for finalizado por exemplo?, processando tudo em paralelo, de forma transparente ao usuário?  Ou mesmo um script para checar a cada N segundos, se determinada aplicação ainda está viva.

É para isso que servem os daemons, ou serviços. Daemons são escritos geralmente em C, Python e outras linguagens, mas porque não utilizamos nosso já conhecido PHP? A principal vantagem disso, é que aproveitamos para criar um ambiente único para a aplicação. Onde todas as peças, rodam sob uma mesma linguagem, facilitando assim a manutenção e aproveitando os profissionais já existentes na equipe, sem contar a reutilização de código ;)

Então, vamos montar um daemon exemplo, utilizando a classe System_Daemon, existente tanto no PEAR quanto no GitHub.

Primeiro, temos que clonar o projeto System_Daemon, de autoria do Kevin van Zonneveld (kvz) no GitHub.

** IMPORTANTE: em meus testes, tive que editar a classe System/Daemon.php, no método ‘isInBackground()’ e removi o ‘self::$_processIsChild &&’ do return, deixando somente o ‘self::isRunning()’. **

Agora vamos ao exemplo de código para rodarmos o daemon. No exemplo abaixo, colo uma estrutura básica de script, que utilizo em meus projetos com Zend, que é meu framework padrão.

defined('APPLICATION_PATH')
    || define('APPLICATION_PATH', __DIR__  . '/../application');

defined('APPLICATION_ENV')
    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));<

set_include_path(
    implode(
        PATH_SEPARATOR,
        array(
            realpath(APPLICATION_PATH . '/../library'),
            realpath(APPLICATION_PATH . '/modules'),
            get_include_path(),
        )
    )
);

/** Zend_Application */
require_once 'Zend/Application.php';

require_once 'system_daemon/System/Daemon.php';

// Create application, bootstrap, and run
$application = new Zend_Application(APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini');
$application->bootstrap();

// Configuro o daemon
System_Daemon::setOption('usePEAR', false);
System_Daemon::setOption("appName", "uploaddaemon");
System_Daemon::setOption("appDescription", "Trata os uploads do site.");
System_Daemon::setOption("appDir", dirname(__FILE__));
System_Daemon::setOption("appExecutable", basename(__FILE__));
#System_Daemon::setOption("appPidLocation", '/var/run/uploaddaemon.pid');
System_Daemon::setOption("logVerbosity", '7');
System_Daemon::setOption("logLocation", '/var/log/uploaddaemon.log');
System_Daemon::setOption("authorName", "Thiago Paes");
System_Daemon::setOption("authorEmail", "mrprompt@gmail.com");

/**
 * Setup the CLI Commands
 * 
 * upload.php --help
 * upload.php --start
 * upload.php --stop
 */
try {
    $opts = new \Zend_Console_Getopt(
        array(
            'help'  => 'Exibe esta ajuda.',
            'start' => 'Inicia o Daemon.',
            'stop'  => 'Encerra o Daemon',
        )
    );

    $opts->parse();
} catch (\Zend_Console_Getopt_Exception $e) {
    exit($e->getMessage() ."\n\n". $e->getUsageMessage());
}

if(isset($opts->help)) {
    echo $opts->getUsageMessage();
    exit;
}

/**
 * Action : start
 */
if(isset($opts->start)) {
    try {
        System_Daemon::start();

        while (true) {
            System_Daemon::log(System_Daemon::LOG_INFO, "rodando...");

            // aguardo um minuto antes de executar novamente a ação
            sleep(60);
        }
    } catch (System_Daemon_Exception $e) {
        System_Daemon::log(System_Daemon::LOG_ERR, $e->getMessage());
    }
}

/**
 * Action : stop
 */
if(isset($opts->stop)) {
    System_Daemon::stop();
}

Pronto, com isso, já temos um exemplo de daemon rodando.

E é isso, divirta-se agora criando seus daemons para melhorar ainda mais suas aplicações e o ambiente delas.


Utilizando PHP na linha de comando com Zend Framework

Quem me conhece sabe que sempre gostei muito de brincar com o Terminal/Prompt, então, tenho costume de criar e utilizar vários scripts para automatizar algumas tarefas repetitivas, nos meus projetos, tenho costume de criar uma pasta ‘bin’, onde coloco os scripts que deverão rodar via Cron ou como um Daemon.

Mas assim como já utilizamos nosso framework favorito para fazermos nossos sites e/ou aplicações, porque não utilizarmos também para fazer nossos scripts?

Meu framework favorito atualmente, é o Zend, principalmente por ser modular - mas isso já é assunto para outro post ou conversa de bar -, então, vou apresentar abaixo, a estrutura básica de um script cli, utilizando o Zend.

<?php
/**
 * Script PHP-CLI exemplo
 */
defined('APPLICATION_PATH')
    || define('APPLICATION_PATH', __DIR__  . '/../application');

defined('APPLICATION_ENV')
    || define(
        'APPLICATION_ENV', (
            getenv('APPLICATION_ENV') ?
            getenv('APPLICATION_ENV') :
            'production'
        )
    );

set_include_path(
    implode(
        PATH_SEPARATOR,
        array(
            realpath(APPLICATION_PATH . '/../library'),
            get_include_path(),
        )
    )
);

// Zend_Application
require_once 'Zend/Application.php';

// E vamos lá, rodando a aplicação com suas configurações
$application = new Zend_Application(
    APPLICATION_ENV,
    APPLICATION_PATH . '/configs/application.ini'
);
$application->bootstrap();

/**
 * Aqui, configuro os parâmetros de entrada válidos
 * 
 * teste.php --help
 * teste.php --start
 * tsete.php --stop
 */
try {
    $opts = new \Zend_Console_Getopt(
        array(
            'help'  => 'Exibe esta ajuda.',
            'start' => 'Inicia.',
            'stop'  => 'Encerra.',
        )
    );

    $opts->parse();
} catch (\Zend_Console_Getopt_Exception $e) {
    exit($e->getMessage() ."\n\n". $e->getUsageMessage());
}

if(isset($opts->help)) {
    echo $opts->getUsageMessage();
    exit;
}

/**
 * Action : start
 */
if(isset($opts->start)) {
    // nosso código
}

/**
 * Action : stop
 */
if(isset($opts->stop)) {
    // nosso código
}

Bom, o código está bem simples de entender e auto explicativo. Basicamente, instanciamos o Zend_Application, normalmente, como fazemos em nosso index.php, para instanciarmos a app e tudo que for necessário para rodar. Em seguida, com o Zend_Console_Getopt, definimos os parâmetros válidos, a partir daí, é só criar as funções de chamadas para as respectivas ações.

Pronto, agora é só dar asas a imaginação e se divertir um bocado com Zend e PHP-CLI.


Sistema de Ponto On Line

A tempos venho escrevendo software pra todo mundo, vários freelas e empresas que já passei, e raramente, tenho a oportunidade/idéia de escrever um software um pouco mais robusto por necessidade própria. Geralmente, escrevo pequenos scripts em PHP-Cli ou Bash mesmo, para automatizar pequenas tarefas, como armazenamento de senhas pessoais, todo list, ponto e etc.

Mas dessa vez foi diferente, como dito a pouco, eu tinha um pequeno script em php-cli, onde registrava meus horários de entrada e saída na empresa que trabalho atualmente. Algo despretensioso, apenas registrava a entrada, saída e me dizia um total de horas, coisa bem simples e totalmente mono usuário. Sempre usei por vontade própria, e para atender somente a minha necessidade de saber se estou cumprindo corretamente meus horários e etc.

Sempre quis fazer uma versão web do script, para poder utilizar nas empresas que passei - acredite, ainda existem empresas que usam o velho cartão ponto, escrito a caneta e fazendo a pobre da secretária executar mil cálculos no final de todo mês - mas nunca me davam a oportunidade de alocar algumas horas para fazê-lo - as empresas sempre cortam nosso barato quando queremos nos divertir.

Então, em uma madrugada, trabalhando encima do projeto de um cliente, me veio um estalo: “- ei, a tempos quero fazer uma interface totalmente em Javascript, mas não posso fazer isso para um cliente, seria muito trabalhoso e não compensaria o esforço.”

Dessa necessidade, nasce o Ponto, um pequeno sistema de Ponto Eletrônico, dessa vez, multi-usuário e muito prático de se utilizar, atendendo perfeitamente a necessidade de pequenas empresas.

A idéia principal - além de atender a minha própria necessidade -, como disse, era poder brincar a vontade com Javascript, mais especificamente, a dupla jQuery + jQuery UI e HTML 5 pra ver no que daria.

Meu foco era o seguinte:

  • escrever o mínimo possível de código HTML, apenas o necessário para carregar o projeto, o resto deveria ser gerado dinamicamente pela aplicação.
  • escrever o mínimo possível de CSS, deixando ao máximo a questão de interface a cargo do jQuery UI.
  • utilizar alguns recursos do HTML 5, como Session Storage.
  • brincar bastante com Javascript :)
  • brincar bastante com SQLite \o/
  • brincar com as “Google Chart Tools

A aplicação é simples e contém os seguintes recursos:

  • cadastro simples
  • cadastro de sub-usuários
  • relatório mensal
  • gráficos de média de assiduidade, cumprimento de  horas diárias e mensal, cumprimento da meta de horas mensais.
  • configuração dos dias da semana em que são trabalhados
  • utilização da sessão do sub-usuário - acho que só quem gosta disso são os chefes.

A base de dados fica armazenada na máquina em que foi aberto o projeto (tanto faz se você jogou em um servidor web ou abriu o arquivo html), e isso quem trata é o próprio navegador. Então, se for utilizar em uma empresa, aconselho a todos os usuários baterem ponto na mesma máquina ;) E por falar em navegador, por enquanto, é compatível apenas com o Google Chrome, pois foi o único que implementou até agora a base de dados interna utilizando SQLite.

Gostou? O código fonte você pode baixar direto da minha página no GitHub ou utilizar a versão de demonstração direto daqui.

Em tempo ainda, se você quiser dar uma conferida no banco que foi criado, basta ter o executável do SQLite3, o banco está num dos caminhos abaixo, dependendo do seu SO: Windows Vista or 7: \Users_username_\AppData\Local\Google\Chrome\User Data\Default\databases Windows XP: \Documents and Settings_username_\Local Settings\Application Data\Google\Chrome\User Data\Default\databases Mac OS X: ~/Library/Application Support/Google/Chrome/Default/databases Linux: ~/.config/google-chrome/Default/databases

Espero que seja útil pra você, quanto é pra mim :)