Layoutside: Construtor de HTML/CSS

Continuo trabalhando aos poucos em meu projeto, já falei sobre ele no blog mas agora quero mostrar também algumas imagens do que estou falando. O nome do aplicativo já foi escolhido e sera Layoutside, esta é a interface do usuário:

Área de trabalho do Layoutside

A interface é bem simples como pode ver contendo um menu e uma barra de ferramentas no rodapé, ambos tem posicionamento fixo.
Continue reading

Executar um comando periódicamente

Existe um comando no linux chamado watch que pode ser bem útil. Você pode por exemplo monitorar um arquivo de log:

$ watch tail /var/log/apache2/error.log

Ou fazer coisas mais nerds como observar como o código em C fica compilado em assembly enquanto você ainda edita o arquivo fonte:

$ watch -d "gcc -S main.c && cat main.s"

Estes são exemplos simples mas trazem uma idéia do que é possível.

Desenvolvimento do projeto

Continuo a trabalhar em meu projeto e as coisas estavam bem corridas, no trabalho e faculdade principalmente. Com isso o projeto tem andado muito devagar, esperava ter publicado algo até este mês mas infelizmente não consegui.

Estou trabalhando nisso sozinho o que dificulta ainda mais, tenho que exercer pelo menos as funções de programador, sysadmin, dba, designer(de protótipos), gerente, analista e tester. Apesar de trabalhoso também é legal, as vezes abro o projeto apenas para testar e montar uma lista de bugs e/ou características novas. Outra vez apenas abro a lista para fazer as correções.

E mesmo todo esse trabalho ainda quero criar projetos novos, estudar coisas legais, escrever no blog, ter vida social e diversão! :D

Projeto pessoal em andamento

Estou desenvolvendo um editor de layout para páginas web. Com este editor será possível criar inúmeros tipos de layouts facilmente, depois de criar seu layout o editor irá gerar o código HTML/CSS para que você possa utilizar e editar como quiser.

O problema

Imagine um layout comum em blogs onde temos áreas como cabeçalho, conteúdo, barra lateral e rodapé. Escrever o código da estrutura deste layout é simples. Agora imagine que precisa escrever o código de um portal com um layout mais complexo como NY Times, WSJ, Globo, Terra ou UOL.

Será uma tarefa bastante trabalhosa considerando que o site tem varias páginas com diferentes layouts e você devera escrever código dentro dos padrões e independente do navegador para cada página.

Solução

Com este editor você poderá construir esses tipos de layout e quaisquer outros como se estivesse ”desenhando”. Justamente por isso a aparência será baseada em editores de imagem como Photshop ou GIMP onde se tem uma área de pintura, menu de configurações e barra de ferramentas.

Resultado

O código HTML/CSS gerado será válido, dentro dos padrões e assim poderá ser utilizado desde a criação de protótipos até a páginas que irão para “produção”. Reutilizar o layout é importante e por isso será possível salvar seu trabalho e até mesmo compartilha-lo com outros usuários.

Pretendo publicar a primeira versão em breve pois estou trabalhando nisso sozinho e tive poucos feedbacks de colégas. Se tiver alguma idéia, opinião ou sugestão deixe seu comentário.

Como fazer log de queries do Doctrine

Para fazer um log de queries executadas pelo Doctrine você pode usar a classe Doctrine_Connection_Profiler, esta classe ira atuar como ouvidora de eventos realizados pela Doctrine_Connection.

Escrevi uma função para isso, para usa-la você ira precisar habilitar o connection profiler, faça o seguinte em seu bootstrap:

$manager = Doctrine_Manager::getInstance();
$profiler = new Doctrine_Connection_Profiler();
$manager->setListener($profiler);

Se estiver usando o bootstrap do post de introdução ao doctrine isso já foi feito. Esta é a função:

<?php

function doctrineLog($logFile = 'php://stdout', $marcador = 'CONNECTION', $dateFormat = 'd-m-Y h:i:s')
{
    $tempo = 0;
    $eventos = $acoes = array();
    $logfp = fopen($logFile, 'a');

    if(!is_resource($logfp))
        return false;

    $profiler = Doctrine_Manager::getInstance()
        ->getCurrentConnection()->getListener();

    fprintf($logfp, "[%s] [START %s]n", date($dateFormat), $marcador);

    foreach ($profiler as $event) {
        $nomeEvento = $event->getName();
        $eventos[$nomeEvento] = isset($eventos[$nomeEvento]) ?
            ++$eventos[$nomeEvento] : 1;

        $tempo += $event->getElapsedSecs();

        if($nomeEvento == 'query' or $nomeEvento == 'execute') {
            fprintf($logfp, "[%s] [Parâmetros] "%s" [Duração] %f [Query] %sn",
                date($dateFormat), join('", "', (array) $event->getParams()),
                $event->getElapsedSecs(), $event->getQuery() );
        }
    }

    $eventos['query'] += $eventos['execute'];

    foreach($eventos as $k => $v)
        $acoes[] = sprintf('%s %s', $v, $k);

    fprintf($logfp, "[%s] [Ações] %s [Tempo Total] %f n",
        date($dateFormat), join(', ', $acoes), $tempo);

    fprintf($logfp, "[%s] [END %s]n", date($dateFormat), $marcador);
    fclose($logfp);
}

Agora invoque a função onde quiser:

<?php

require 'bootstrap.php';
// incluir a função
require 'functions.php';

$actorTable = Doctrine::getTable('Actor');
$actor = $actorTable->find(155);
$julia = $actorTable->findOneBy('first_name', 'Julia');

$customerTable = Doctrine::getTable('Customer');
$customers = $customerTable->findAll();

// imprimir log de queries executadas até aqui
echo '<pre>';
doctrineLog('php://output');
echo '&lt;/pre>';

$cityTable = Doctrine::getTable('City');
$citys = $cityTable->findAll();
$city = $cityTable->findOneBy('city', 'London');

$filter = Doctrine_Query::create()
  ->from('Actor a')
  ->leftJoin('a.Filmes f')
  ->where('a.actor_id = ? AND f.rating = ?')
  ->execute(array(68, 'PG-13'));

// log em um arquivo comum
doctrineLog('log/querylog.txt');
// log em um arquivo compactado com gzip
doctrineLog('compress.zlib://' . dirname(__FILE__) . '/log/querylog.gz');

?>

Resultaria em:

[15-04-2010 19:22:36] [START CONNECTION]
[15-04-2010 19:22:36] [Parâmetros] "155" [Duração] 0.000205 [Query] SELECT a.actor_id AS a__actor_id, a.first_name AS a__first_name, a.last_name AS a__last_name, a.last_update AS a__last_update FROM actor a WHERE (a.actor_id = ?) LIMIT 1
[15-04-2010 19:22:36] [Parâmetros] "Julia" [Duração] 0.000185 [Query] SELECT a.actor_id AS a__actor_id, a.first_name AS a__first_name, a.last_name AS a__last_name, a.last_update AS a__last_update FROM actor a WHERE (a.first_name = ?) LIMIT 1
[15-04-2010 19:22:36] [Parâmetros] "" [Duração] 0.000647 [Query] SELECT c.customer_id AS c__customer_id, c.store_id AS c__store_id, c.first_name AS c__first_name, c.last_name AS c__last_name, c.email AS c__email, c.address_id AS c__address_id, c.active AS c__active, c.create_date AS c__create_date, c.last_update AS c__last_update FROM customer c
[15-04-2010 19:22:36] [Ações] 1 connect, 2 prepare, 2 execute, 4 fetch, 3 query [Tempo Total] 0.014827
[15-04-2010 19:22:36] [END CONNECTION]

O log irá para a saída padrão do PHP ou para outro arquivo como no exemplo. Esta função apenas registra o log em um arquivo então você pode criar sua “estratégia” para fazer os log’s.

Relacionamentos Many-to-Many no Doctrine

Many-to-Many relation

Doctrine também suporta o relacionamento N:M ou muitos para muitos como no caso da figura ao lado, um ator pode fazer vários filmes e um filme pode ter vários atores. Essa definição é um pouco diferente das demais, por exemplo um relacionamento entre de usuários e grupos, ambas as entidades tem que receber uma definição para a relação e uma nova tabela é criada para ligar as duas relações.

Continue reading

Executanto operações CRUD com Doctrine

Executar operações CRUD é algo que temos que fazer muito na maioria de nossos projetos e geralmente isso é algo repetitivo e até tedioso. Existem frameworks que facilitam bastante com o scaffolding no entanto tem a desvantagem de retirar sua flexibilidade na personalização destas operações e das views geradas.

Com ORM a parte lógica destas operações fica bem simples sem retirar sua flexibilidade, você ainda precisara criar suas views/html mas pode fazer como bem entender e com isso usar validações dinâmicas, validar regras de negocio, utilizar AJAX em seus componentes, etc.

Continue reading