Sei sulla pagina 1di 8

Gerando gráficos com PHP e highcharts.

com

Alô Comunidade PHP! Neste artigo eu pretendo mostrar como preencher uma
lacuna no desenvolvimento de aplicativos gerenciais que dependem de 2 gráficos
importantes: Pizza e Linhas. Soluções como o PHPLot funcionam, mas não dão o
resultado esperado. Vamos lá?

1 - Introdução:
Sempre que posso eu pesquiso alguma forma nova de fazer o meu trabalho, uma
forma nova de aumentar minha produtividade. Ultimamente tenho estudado SCRUM,
técnica pomodoro e outras formas de realizar autogerenciamento sem que isso se torne
um parto. Tive uma última demanda por gráficos para os meus projetos, um aplicativo
de controle dos meus contratos e também um de finanças pessoais (que posso comentar
em outros artigos) e os implementei num primeiro momento com o PHPLot que é fácil,
leve e dá um bom resultado, porém não era ainda o que eu queria. Eu queria mesmo era
uma coisa parecida com os gráficos do Google Analytics, ou seja, algo em javascript, de
preferência Jquery. Procurando encontrei o highcharts (hicharts.com).
Como eu sempre evito parar pra escrever código javascript, automatizo a criação
do resultado com PHP. Crio uma classe em PHP que faça a parte chata do trabalho, ou
seja, gerar o código javascript, chamar o arquivo do plugin etc. Resultado:
produtividade lá em cima.

2 – A situação do gráfico de linhas:


Pensa naquele gráfico bonito mostrando o andamento de uma situação, seja ela o
saldo atual de suas contas, o desenvolvimento de um trabalho, a cotação do dólar etc.
Essas são situações exemplo para a utilização desse tipo de gráfico e que são facilmente
resolvíveis com o highcharts e com PHP. Os dados a serem passados são poucos, o
resultado é ótimo.
Vamos exemplificar aqui uma série de quinze dias de resultados de saldos de uma
determinada conta, pode ser uma poupança, uma conta banco movimento ou qualquer
que você queira usar como exemplo para reproduzir. Os resultados serão, aqui, do dia
primeiro ao décimo quinto dia de um dados mês onde os dados serão apresentados em
forma de um array, onde o índice do array que contém os dados é o legenda para essa
série e nos arrays aninhados o valor do índice zero é o dia e do índice hum valor é o
saldo. Entendido?
Vamos aos dados então:
$dados = array('Saldo'=>array(
array(1, 900 ),
array(2, 1205 ),
array(3, 1351 ),
array(4, 1300 ),
array(5, 1285 ),
array(6, 1555 ),
array(7, 2001.5 ),
array(8, 1916.15 ),
array(9, 1894 ),
array(10, 2201 ),
array(11, 1863.81 ),
array(12, 3332.21 ),
array(13, 3332.21 ),
array(14, 3110.21 ),
array(15, 2900.21 )
));

3 – A classe LineChart
Para solucionar o problema vamos criar a class LineChart (no meu caso eu a
estendo de outra class, a TSWObject, mas isso aqui não vem ao caso, o resultado não
depende diretamente disso). A implementação é a seguinte:
<?php
/**
* LineChart
* Classe que implementa a abstração de gráficos highcharts.com para
* gráfico de linhas.
*
* @author Evaldo Barbosa <tryadesoftware@gmail.com>
*/
class LineChart /*extends TSWObject*/ {
private $container;
private $title;
private $subtitle;
private $yAxis;
private $series;

/**
* Construtor da classe.
* @param array $conf Array com as configurações para que o gráfico funcione.
* As chaves desse array deve ser iguais aos nomes dos atributos internos dessa
classe.
* Perceba que o índice title pode ter mais de um índice, equivalentes a título e
subtítulo respectivamente.
* @return void
*/
function __construct($conf) {
$this->title = $conf['title'][0];
$this->subtitle = $conf['title'][1];
$this->container = $conf['container'];
$this->series = $conf['series'];
$this->yAxis = $conf['y'];
}

/**
* Método que gera os dados e os retorna para implementação na página.
* @return string
*/
function render() {
//A linha abaixo foi comentada porque a mesma chama uma outra classe
//que uso para facilitar a geração das minhas tags internas do header
//da página como tags de chamadas de arquivos CSS <link>
//de chamadas de arquivos JS ou códigos JS personalizados sob demanda
//que nela chamo de LiveScripts. Idéia para outro artigo!
//Header::addJSFile("linechart","/js/highcharts/highcharts.js");

$series = array();
$data = array();
$axis = array();
foreach ( $this->series as $key=>$row ) {
$data[$key] = array();
foreach( $row as $_row ) {
$axis[] = $_row[0];
$data[$key][] = $_row[1];
}
}
$axis = "'" . implode("','",$axis) . "'";

foreach( $data as $key=>$row ) {


$i = implode(",",$row);
$series[] = "{name:'{$key}',data:[{$i}]}";
}
$series = implode(",",$series);

$str = "chart = new Highcharts.Chart({


chart: {
renderTo: '{$this->container}',
defaultSeriesType: 'line',
marginRight: 130,
marginBottom: 25
},
title: {
text: '{$this->title}',
x: -20 //center
},
subtitle: {
text: '{$this->subtitle}',
x: -20
},
xAxis: {
categories: [{$axis}]
},
yAxis: {
title: {
text: '{$this->yAxis['title']}'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
formatter: function() {
return '<b>'+ this.series.name +'</b><br/>'+
this.x +': '+ this.y;
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
x: -10,
y: 100,
borderWidth: 0
},
series: [{$series}]
});
";
//Lembra que falei do LiveScript?
//Header::addLiveScript( $str );
return $str
}
}
?>
A implementação original foi modificada para que não houvesse dependência em
relação a nenhum outro arquivo ou classe do meu framework, salve o código acima num
arquivo chamado linechart.php, iremos usá-lo em breve. Vamos agora ao HTML que
receberia esse o resultado desse código.
Chamemos o arquivo de linechart_exemplo.php que conterá o código PHP que
usará a classe anterior e também o HTML que será a interface com o gráfico. Vamos ao
código!
<html>
<head>
<title>Exemplo de LineCharts com PHP e Highcharts</title>
<!-- LEMBRE-SE DE BAIXAR OS ARQUIVOS DO JQUERY E HIGHCHARTS.COM /-->
<script src=”js/jquery.js”></script>
<script src=”js/highcharts.js”></script>
<script>
<?
require(“linechart.php”);
$dados = array('Saldo'=>array(
array(1, 900 ),
array(2, 1205 ),
array(3, 1351 ),
array(4, 1300 ),
array(5, 1285 ),
array(6, 1555 ),
array(7, 2001.5 ),
array(8, 1916.15 ),
array(9, 1894 ),
array(10, 2201 ),
array(11, 1863.81 ),
array(12, 3332.21 ),
array(13, 3332.21 ),
array(14, 3110.21 ),
array(15, 2900.21 )
));
$charts = new LineChart(array(
"title" => array("Seu desempenho nos últimos 15 dias","Acompanhamento
diário"),
"container" => "container",
"y" => array(
"title"=>"Em R$"
),
"series" => $dados
));
?>
$(document).ready(function() {
<? echo $charts->render(); ?>
});
</script>
</head>

<body>
<div id=”container”><!-- AQUI FICARÁ O GRÁFICO /--></div>
</body>

</html>

De posso do HTML e do código que gera o gráfico, mãos à obra!

Visto o resultado, vamos ao próximo gráfico.

4 – A situação do gráfico pizza:


Essa é uma situação bem corriqueira e simples de pensar e resolver. A
circunferência completa equivale a 100% e cada categoria dada tem a sua porcentagem.
Um exemplo é a distribuição de gastos entre categorias como alimentação, lazer,
transporte etc.
Para esse gráfico a abordagem é bem parecida à abordagem anterior, ou seja, os
dados serão passados como um array. Vamos a ele:
$dados = array( array("FREE LANCE",8.87), array("SALARIOS",84.01),
array("Poupança",7.12)) ;

5 – A classe PieChart:
Como no exemplo anterior vamos criar uma classe, dessa vez a PieChart, que
desempenhará o mesmo papel de abstrair o javascript facilitando a geração do gráfico
sem ter que meter a mão direto no Jquery. O código segue abaixo:
<?php
/**
* PieChart
* Classe que implementa a abstração de gráficos highcharts.com para
* gráfico tipo pizza.
*
* @author Evaldo Barbosa <tryadesoftware@gmail.com>
*/
class PieChart extends TSWObject {
private $container;
private $title;
private $subtitle;

/**
* Construtor da classe.
* @param array $conf Array com as configurações para que o gráfico funcione.
* As chaves desse array deve ser iguais aos nomes dos atributos internos dessa
classe.
* Perceba que o índice title pode ter mais de um índice, equivalentes a título e
subtítulo respectivamente.
* @return void
*/
function __construct($conf) {
$this->title = $conf['title'][0];
$this->subtitle = $conf['title'][1];
$this->container = $conf['container'];
$this->series = $conf['series'];
}

/**
* Método que gera os dados e os retorna para implementação na página.
* @return string
*/
function render() {
$series = array();
foreach ( $this->series as $row ) {
$row[1] = sprintf("%01.2f",$row[1]);
$series[] = "['{$row[0]}',{$row[1]}]";
}
$series = implode(",",$series);

//Header::addJSFile("piechart","/js/highcharts/highcharts.js");
$str = "chart = new Highcharts.Chart({
chart: {
renderTo: '{$this->container}',
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false
},
title: {
text: '{$this->title}'
},
tooltip: {
formatter: function() {
return '<b>'+ this.point.name +'</b>: '+
this.y +' %';
}
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: false
},
showInLegend: true
}
},
series: [{
type: 'pie',
name: '{$this->subtitle}',
data: [{$series}]
}]
});";
//Lembra que falei do LiveScript?
//Header::addLiveScript( $str );
return $str;
}
}
?>
O código HTML para este exemplo é muito semelhante ao outro, a diferença fica a
cargo somente no array de dados e na chamada para a classe PieChart. Mas para que não
fique muito vago, apresentarei o bloco onde haverá a mudança. Veja o código que será
modificado no header:
<script>
<?
require('piechart.php');
$dados = array( array("FREE LANCE",8.87), array("SALARIOS",84.01),
array("Poupança",7.12)) ;
$charts = new PieChart(array(
"title" => array("Visão geral das suas receitas","Distribuição por categoria"),
"container" => "container",
"series" => $dados
));
?>
$(document).ready(function() {
<? echo $charts->render(); ?>
});
</script>
Salve esse código como piecharts_exemplo.php e rode no seu browser, o resultado
será assim:
6 – Conclusão:
Todos sabemos que gráficos deixam a informação mais elegante e mais fáceis de
ler. Gráficos com informações consistentes fazem com que o gestor possa tomar decisões
mais rapidamente sem analisar uma massa de dados, pois a função que eles
desempenham é justamente a de sintetizar uma visão tirada de uma amostra de dados.
Fazer com que o PHP automatize a tarefa chata de incluir o Javascript dentro de
uma paǵina HTML ao estilo macarrão, ou mesmo dentro de um template Smarty ou outra
suite de templates cria, além da sensação de poder fazer mais rápido, uma melhor
estrutura para manutenção do código.
A todos aqueles que tiverem dúvidas ou sugestões a fazer para as classes podem
entrar em contato comigo através de e-mail ou então podem me encontrar no twitter
em @evaldobarbosa para trocarmos ideias.
Aguardem outros artigos.

Potrebbero piacerti anche