Onego czasu próbowałem znaleźć coś co ułatwiłoby mi rysowanie prostych wykresów w PHP’ie inaczej niż z palca w GD. Kumpel polecił mi JPGraphexternal link .

JPGraph to świetna sprawa, do generowania statystyk jak chociażby na mojej stronie, ale biblioteka potrafi dużo więcej…

Załóżmy, że ze stronki zbieramy do bazy takie rzeczy jak: datę, adres IP, ilość połączeń z tego adresu. Prosta tabela (przykład w Postgre SQL’u):

CREATE TABLE wizyty
(
  pid serial NOT NULL,
  "data" date NOT NULL DEFAULT ('now'::text)::date,
  odslony integer NOT NULL DEFAULT 1,
  CONSTRAINT visits_pkey PRIMARY KEY (id)
);

Dane z takiej tabeli można łatwo wyciągnąć jednym select’em:

SELECT date_part('day', "data") AS x, sum(odslony) AS y
FROM wizyty
WHERE date > ('today'::date - '30 days'::interval)
GROUP BY "data"
ORDER BY "data"
LIMIT 30

Powyższe zapytanie wyciągnie nam z kolumny z datą tylko dzień miesiąca, który posłuży za etykietę (oś X) oraz sumę odsłon z danego dnia (oś Y), posortowane według daty i tylko z ostatnich 30 dni.

W zależności od sposobu dostępu i pobierania wyników, trzeba je ładnie zapisać w dwóch tablicach. Ja to robię w prostej pętli:

foreach ($query->result() as $row) {
  $x[] = $row->x;
  $y[] = $row->y;
}

Mając dane została zabawa z ustawieniem oczekiwanych opcji wykresu:

/* bez tego ani rusz */
include_once 'jpgraph/jpgraph.php';
include_once 'jpgraph/jpgraph_bar.php';

/* szerokość */
$width = 400;

/* wysokość */
$height = 300;

$graph = new Graph($width, $height);

/* oś X tekst, oś Y wartości całkowite */
$graph->SetScale("textint");

/* kolorowa ramka */
$graph->SetFrame(true, '#222222');
$graph->SetMarginColor('#222222');

/* tytuł wykresu, trochę konfiguracji fontów i kolorów */
$graph->title->Set('Sumaryczna liczba odsłon');
$graph->title->SetFont(FF_VERDANA,FS_BOLD,10);
$graph->title->SetColor('#999999');

/* podobnież jak powyżej dla osi X */
$graph->xaxis->SetFont(FF_VERDANA,FS_NORMAL,8);
$graph->xaxis->SetColor('#999999');
$graph->yaxis->SetFont(FF_VERDANA,FS_NORMAL,8);
$graph->yaxis->SetColor('#999999');

/* dodatkowe ozdobniki ;) */
$graph->yscale->ticks->SupressZeroLabel(false);
$graph->yscale->ticks->SetColor('#999999');
$graph->xaxis->SetTickLabels($x);

/* genrujemy właściwy wykres, w tym przypadku słupkowy */
$bplot = new BarPlot($y);
$bplot->SetWidth(0.6);
$bplot->SetFillColor('#D01A71@0.25');
$bplot->SetColor('gray');

/* dodajemy wykres do obiektu $graph (który to może pomieścić
i wyświetlić wiele wykresów, co z resztą pokazane jest poniżej) */
$graph->Add($bplot);

/* teraz wykres liniowy */
$lplot = new LinePlot($y);

/* z wypełnieniem pod wykresem */
$lplot->SetFillColor('skyblue@0.5');
$lplot->SetColor('navy@0.7');
$lplot->SetBarCenter();

/* typ znacznika na łącznikach pomiędzy kolejnymi słupkami */
$lplot->mark->SetType(MARK_SQUARE);
$lplot->mark->SetColor('blue@0.5');
$lplot->mark->SetFillColor('lightblue');
$lplot->mark->SetSize(6);

/* wrzucamy kolejny wykres do obrazu */
$graph->Add($lplot);

/* a teraz magia... */
$graph->Stroke();

Co to robi… Ano dokładnie taki wykres jak ten poniżej:

Histogram of all visits
Histogram of all visits

Co prawda ten wykres nie odpowiada w 100% podanemu źródłu. To statystyka z mojej strony, która niebieską linią zaznacza volumen pobranych danych - przykład jest nieco uproszczony.

Na pierwszy rzut oka powyższy skrypt wydaje się dość długi i jest tam dużo nie do końca jasnych opcji, ale najfajniejsze jest to, że tak na prawdę nie trzeba się tego uczyć. Biblioteka domyślnie dostarczana jest z masą przykładów. Wystarczy wybrać wykres podobny do tego, który sami chcemy zrobić - skopiować większość kodu. Znaleźć inne wykresy, których cechy chcemy powielić i po kilku próbach skleimy takiego Frankenstein’a jakiego świat nie widział wcześniej ;-D

Mój wykres akurat ma trochę zmieniony kolor tła ramki i fonty, tak aby lepiej wkomponował się w moją stronę - reszta bazuje na dwóch przykładach z dokumentacji. Na zrobienie pierwszego wykresu z wykorzystaniem JPGraph potrzebowałem ok. godziny. Teraz wystarcza mi 10 minut 😃