sexta-feira, 28 de janeiro de 2011

Macetes: Comparando data e hora em PHP utilizando MySQL

O PHP não é muito feliz quando o assunto é comparar data e hora, sempre que procuro boas alternativas para fazer isto no PHP, continuo ainda preferindo a versão do MySQL, que uso já há algum tempo. Por incrível que pareça ela ainda consegue ser mais limpa, rápida e acurada do que as soluções feitas somente em PHP.

Para fazer esta comparação em MySQL basta utilizar a função TIMEDIFF dentro de uma query SELECT:

SELECT TIMEDIFF('AAAA-MM-DD HH:MM:SS', 'AAAA-MM-DD HH:MM:SS')

Se o primeiro parâmetro for uma data menor que o segundo, então o valor retornado será negativo, o que pode ser bom para em casos que você tenha que descobrir se algo já passou de algum prazo estipulado.

No PHP você poderia trabalhar da seguinte forma:


$sql = mysql_query("SELECT TIMEDIFF('2011-01-28 09:00:00','2011-01-28 00:00:10') as dif");

$time = mysql_fetch_array($sql);

echo($time[dif]);

O resultado final será a diferença em horas, o que em muitos casos é o suficiente, agora se você precisa de outros formatos, terá que recorrer a outras funções.

Até a próxima!

quinta-feira, 27 de janeiro de 2011

Macetes: Javascript, substituindo todas as ocorrências dentro de uma string (Replace All)

Ao contrário do PHP, o JavaScript não possui funções que fazem o replace de várias ocorrências de uma substring dentro de uma string, como acontece nas funções muito conhecidas pelos desenvolvedores do elefante azul: preg_replace() e str_replace().

Você pode até procurar e encontrar na net, funções denominadas replaceAll() que fazem este trabalho para você no Java Script, mas nenhuma delas é nativa da linguagem e sim funções criadas por usuários.

Infelizmente, como ocorreu comigo, estas funções geralmente apresentam bugs, principalmente quando você precisa escapar caracteres como \ (contra barra) e " (aspas duplas), que comumente precisam deste tipo de tratamento quando estamos trabalhando com strings.

O único método nativo do Java Script para fazer substituição dentro de strings é o método replace(), ele por padrão substitui apenas o primeiro valor encontrado e é ele quem serve de base para aquelas funções customizadas citadas anteriormente. Para felicidade geral, este método esconde um pequeno segredinho, que faz ele mudar seu comportamento e substituir todas as ocorrências dentro de um string. Confira abaixo:

//Uma string qualquer
var str = 'Vou incomodar você com estas "aspas duplas"';

//A primeira aspas duplas encontrada ganhará uma contra barra grátis
str = str.replace(/\"/,'\\"');

//Resultado: Vou incomodar você com estas \"aspas duplas"
document.write(str);

Como dito, apenas a primeira aspas duplas ganhou a contra barra, agora vamos utilizar o modificador g para fazer um Global Match e substituir todas as " por \".

//Uma string qualquer
var str = 'Vou incomodar você com estas "aspas duplas"';

//Repare onde você deve colocar o modificador (destacado em azul)
str = str.replace(/\"/g,'\\"');

//Resultado: Vou incomodar você com estas \"aspas duplas\"
document.write(str);

Espero que este macete possa lhe ajudar como me ajudou, apesar do "lance" das aspas ser apenas um exemplo, ele pode causar vários problemas, principalmente quando você esta criando uma string para criar um objeto JSON e dentro desta string você precisa permitir que sejam passados valores com aspas duplas, se elas não forem devidamente escapadas antes de você concatenar seu valor na string JSON, com certeza o Java Script vai berrar.

Abraço!

quarta-feira, 26 de janeiro de 2011

Macetes - Regex no Notepad++ - Reescrevendo valores

Vamos explicar este macete com uma pequena historinha, se quiser pulá-la e ir direto ao ponto, clique aqui.

Digamos que seu chefe passou hoje por você, te achou meio ocioso e decidiu sacanear você um pouco. Trouxe então uma planilha do Excel com uma lista interminável de clientes e pediu que você excluísse do sistema da empresa, todos os clientes que estão marcados como "desativado" na planilha.

Você sacando a jogada do seu chefe, aceitou de boa e ainda exclamou: "Meu, isso vai levar a tarde inteira, senão um dia inteiro!". Seu chefe, vendo seu desespero apenas respondeu: "Então, boa sorte!"

Como você já havia lido o post: "Macetes - Regex no Notepad++ - Reescrevendo valores" no Programação de Resultado, você calmamente acessou a já conhecida planilha e sabiamente ordenou todos os registros pelo id do cliente, que felizmente é igual tanto na planilha quanto no sistema. Selecionou então a coluna e colou todos os ids no seu Notepad++.

Em seguida com grande familiaridade, deu um CTRL+F na janela do Notepad++ e abriu a janela de Localizar, selecionou Expressão regular no canto inferior esquerdo da janela e digitou a seguinte expressão no campo Localizar : ([0-9]+), conferiu então se a expressão funcionou corretamente clicando no botão Localizar próximo e constatou que tudo ocorre bem.

Na sequência, ainda na janela Localizar, clicou na aba Substituir, posicionou o cursor do mouse no campo Substituir por e então digitou: DELETE FROM clientes WHERE id = \1;. Por fim clicou no botão Substituir todos e o Notepad++ fez a mágica de criar uma query para cada número encontrado no arquivo, você apenas executou a query no banco de dados e "Voilà", todos os clientes desativados foram excluídos do sistema como seu chefe pediu.

Agora, de duas uma, ou você chega para o seu chefe 5 minutos depois de te passar esta tarefa e diz que esta pronto fazendo "mó média" e ele apesar de espantado percebe que você sabia que ele tava te sacaneando e então você se aproveitou para sacanear ele também, mostrando o quanto você é bom e que não pode ser enrolado com essas tarefas frívolas, portanto ele decide contra sacanear e te passa mais trabalho (que frase longa), ou você faz tudo em 5 minutos e enrola um dia inteiro para entregar e chega para ele dizendo: "Aquela tarefa, esta pronta!", ele te questiona "Ok! Deu muito trabalho?", você fazendo aquela cara de "Ufa!", diz: "Que nada chefe, precisando estamos aí!".

A decisão é sua.

Explicando o macete

No notepad++ digite entre parênteses, uma expressão regular qualquer, isto informa ao Notepad++ que você esta procurando um grupo de caracteres em particular, estando a expressão entre parênteses você consegue utilizar o valor encontrado na hora de substituí-lo por outro, é como se nós concatenássemos o valor encontrado ao novo valor que queremos escrever.

No exemplo nós utilizamos: ([0-9]+), para encontrar todos os números possíveis no arquivo, o valor encontrado para esta expressão, ficará armazenado pelo Notepad++ e você poderá acessá-los por meio de uma série de palavras reservadas: \1, \2, \3, \4, \5 ..., sendo que \1 representa o valor encontrado no primeiro grupo, \2 o valor encontrado para o segundo grupo encontrado e assim por diante.

Espero que tenham apreciado o post. Até a próxima.

quarta-feira, 19 de janeiro de 2011

Vídeo: Desconectar para conectar

Hoje pela manhã fui surpreendido por este vídeo, confesso que me arrepiei.
Se trata de um comercial de uma empresa telefônica que basicamente mostra a maneira como nos entretemos em nossos celulares "mil e uma utilidades" para ficar em contato com outras pessoas e acabamos esquecendo aqueles que estão a nossa volta.

Como o blog trata de tecnologia, não pude deixar de postar.

Confira o vídeo:



A contribuição é do meu amigo Marcos Minharo.

segunda-feira, 10 de janeiro de 2011

Tutorial: Paginação em ajax, utilizando a classe Paging e o plugin Jquery Table Sorter

Como sei que paginação em php é (quase)sempre um problema, resolvi criar uma classe para fazer esse trabalho por mim de uma maneira bem simples e escalável, é a classe Paging, que já foi apresentada anteriormente nos posts: Paginação simples e rápida em PHP utilizando a classe Paging e Tutorial: Utilizando a classe Paging para criar uma paginação simples e rápida.

Na versão em que ela se encontra, os únicos dados que conseguimos paginar são resultados tabelados, ou seja gerar um grid de dados com paginação, mas a idéia é futuramente poder paginar vários tipos de dados, como conteúdo html e imagens, porém, como falta-me tempo não consegui implementar métodos para isso, se você quiser contribuir fique a vontade. Deixando o papo de lado, vamos a solução.

Criando paginação utilizando ajax

Arquivos necessários

Para este tutorial iremos utilizar a biblioteca Jquery e o plugin Jquery Table Sorter. Ambos já estão inseridos no arquivo compactado disponível para download abaixo, juntamente com a classe Paging e os demais arquivos necessários para criar a paginação em ajax.

Entendendo os arquivos

/css

Neste diretório você irá encontrar duas folhas de estilos, uma utilizada simplesmente para estilizar o arquivo index.html e a outra é a folha de estilização padrão baixada juntamente com o plugin Jquery Table Sorter.

/img

Neste diretório são encontradas apenas imagens utilizadas no plugin Jquery Table Sorter.

/lib

Aqui você encontrará dois subdiretórios: /js e /php, neles você encontrará o a biblioteca Jquery e o plugin Jquery Table Sorter, além da classe de paginação Paging e a classe Connection, utilizada pela classe Paging para fazer uma conexão com um banco de dados. Caso você tenha dúvidas de como implementar esta conexão de uma olhada neste tutorial. Você não vai precisar mexer em nada nestes arquivos, a não ser que queira inserir novos métodos.

produtos.sql

Utilizamos este sql apenas para este exemplo, mas você pode facilmente configurar nossa solução para a tabela que você quiser.

paging.js

Este arquivo é quem faz o trabalho de criar as chamadas em ajax, para fazermos uma paginação sem recarga de página, a não ser que você queira implementar alguma nova funcionalidade, não é preciso mudar nada nele.

index.php

Neste documento encontramos a marcação necessária para apresentarmos os elementos básicos de nossos dados paginados:
  1. Uma div para procurarmos registros (search)
  2. Uma div que irá mostrar os registros encontrados (grid)
  3. Uma ou mais divs para mostrar os controles da paginação (controls)
  4. As chamadas a estilos e scripts necessários para fazer o "show" acontecer.
No arquivo que você for implementar esta solução, você não precisa nomear os ids/classes das divs exatamente como neste exemplo (grid, controls e search), fique livre para nomeá-los como achar melhor.

Criando paginação em ajax configurando apenas dois arquivos

grid.php

Este é um dos dois arquivos que você precisará alterar para fazer a mágica acontecer, são apenas 6 linhas que teremos que alterar (em negrito):

require_once('lib/php/paging.class.php');
$paging = new Paging();
$searchfor = isset($_GET['searchfor']) ? $_GET['searchfor'] : '';
$paging->table('produtos');
$paging->where('id = "'.$searchfor.'" OR nome LIKE "%'.$searchfor.'%" OR tipo LIKE "%'.$searchfor.'%"');
$paging->labels('ID,Nome,Tipo');
$paging->fields('id,nome,tipo');
$paging->cols_width('10,100,40');
$paging->rowsperpage(10);
$paging->page(isset($_GET['p']) ? $_GET['p'] : 1);

if($_GET['load'] == 'controls'){

$paging->show_controls();

}else{

$paging->show_table();

}
  1. require_once('lib/php/paging.class.php'); - altere para o diretório onde você irá armazenar as classes paging.class.php e connection.class.php
  2. $paging->table('produtos'); - informe o nome da tabela que contém os dados que deverão ser paginados
  3. $paging->where... - caso você opte por inserir a função search ao grid, defina aqui quais campos e condições para que os dados sejam mostrados, a sintaxe vai ser sempre similar a mostra neste exemplo, basicamente serão apenas os campos buscados que irão mudar.
  4. $paging->labels('ID,Nome,Tipo'); - Aqui serão definidos os cabeçalhos do grid
  5. $paging->fields('id,nome,tipo'); - Aqui você deve informar quais as colunas da tabela, que você deseja mostrar
  6. $paging->cols_width('10,100,40'); - Esta linha é opcional, mas caso você venha a ter problemas com os tamanhos (width) das colunas do grid, você pode ajustá-las aqui, basta colocar os tamanhos separados por vírgula para as respectivas colunas.
Você pode configurar ainda mais sua paginação, confira todos os métodos disponíveis para a classe acessando o post: Paginação simples e rápida em PHP utilizando a classe Paging.

param.js

Este é o segundo e último arquivo que você terá que modificar, não tem muito o que explicar nele, pois esta tudo devidamente comentado, de qualquer forma vamos mostrar aqui apenas para você ver como é fácil:
Configurando os controles da paginação
  1. var controlsdivclass = '.paging'; - Informe aqui em quais divs você deseja mostrar os controles da paginação, você pode ter os mesmos controles em diferentes divs;
  2. var controlsscript = 'grid.php'; - Informe aqui qual arquivo irá processar os registros e criar os controles;
  3. var controlsclass = 'tablesorter'; - Classe utilizada para estilizar os controles
Configurando o grid
  1. var griddivid = '#grid'; - Informe a div onde será mostrado o grid
  2. var gridscript = 'grid.php'; -Informe aqui qual arquivo irá processar os registros e criar o grid;
  3. var controlsclass = 'tablesorter'; - Classe utilizada para estilizar o grid
  4. var gridheaders = {}; - objeto utilizado para passar instruções ao plugin Jquery Table Sorter, parametrizando os cabeçalhos da tabela individualmente, algo do tipo: 0:{sorter:false}, 1:{sorter:false}...
Outros parâmetros
  1. var consolediv = '#console'; - Div utilizada para mostrar mensagens de status da execução
  2. var loadmsg = 'Carregando...aguarde'; - mensagem ou caminho para um gif animado para ser mostrado enquanto os dados estão sendo carregados
  3. var searchid = '#searching'; - Id do input (text) que será utilizado para fazer o search dentro do grid.
Configurando corretamente, você terá um resultado semelhante ao abaixo. Tente fazer isso para suas tabelas, você verá como ficará fácil implementar paginação no seu site ou sistema.


Resultado final da paginação com classe Paging + Ajax (Jquery e Jquery Table Sorter)

Se você é um usuário já experiente em Jquery, deve estar se perguntando porque eu não criei este grid como um plugin jquery, já que seria bem mais fácil de configurá-lo ao invés de utilizar um arquivo para configuração, a verdade é que eu nunca criei um plugin jquery, pois até então nunca tive a necessidade, a idéia é que eu transforme este grid em um plugin mais tarde, assim que eu tiver tempo para isso, se você já tem experiência no assunto, gostou da solução, tiver idéias ou quiser contribuir, fique a vontade, eu adoraria transformar isto em um plugin, principalmente em um gratuito, já que o plugin para criar grids com jQuery oficial (jqGrid) que existe hoje é uma solução paga.

É isso então, espero que tenham apreciado, deixem seus comentários, sugestões ou dúvidas que terei prazer em atendê-los. Até a próxima!