16.2 Einbindung in die Applikation 

In Kapitel 15, »Logging«, wurden die Zugriffe auf Blog-Einträge und dabei auch der Browser und das Betriebssystem des Besuchers festgehalten. Aus diesen Informationen sollen in diesem Kapitel Graphiken zur visuellen Auswertung der Zugriffe erstellt werden.
Dazu werden Statistiken über die Aufteilung von Browsern und Betriebssystemen angezeigt. Die Statistik zu den Betriebssystemen soll klickbar sein, damit Sie die Aufteilung der Browser pro Betriebssystem erkennen können. Dazu wird die Anzahl der Aufrufe der einzelnen Blog-Einträge visualisiert, deren langfristige Entwicklung der Popularität in einer berechneten durchschnittlichen Kurve angezeigt werden soll.
16.2.1 Die Aktion erstellen 

Die Aktion, die die Diagramme generiert, wird in die autoload-Datei und in die Konfigurationsdatei eingetragen. Die erstellten Graphiken sollen im Verzeichnis images/graph/ abgelegt werden. Es werden zwei Aktionen registriert: eine für die Übersicht und eine für die Detailübersicht für ein einzelnes selektiertes Betriebssystem.
public static function registerSlots()
{
gpBlogController::getInstance()->actionSignals->connect(
"statistics",
array( __CLASS__, "overview" )
);
gpBlogController::getInstance()->actionSignals->connect(
"os_statistics",
array( __CLASS__, "byOs" )
);
self::$imagePath = realpath(
dirname( __FILE__ ) . '/../../htdocs/images/graph/'
) . '/';
}Listing 16.1 Signale für Statistiken registrieren
Da der Dateipfad für jede erstellte Graphik verwendet wird, wird er in der statischen Eigenschaft $imagePath gespeichert. Die statischen Methoden, die die eigentlichen Aktionen implementieren, generieren die Graphiken über den Aufruf dezidierter Methoden.
public static function overview(
ezcUrl $url, ezcUrlConfiguration $config )
{
$graphs = array();
$graphs[] = self::generateBrowserStatistics();
$graphs[] = self::generateOSStatistics();
$graphs[] = self::generateHitStatistics();
// Fix paths
foreach ( $graphs as $nr => $path )
{
$graphs[$nr] = substr(
$path,
strpos( $path, '/images/' )
);
}
gpBlogController::getInstance()->mainSignals->emit(
"display",
"statistics",
array(
'graphs' => $graphs,
)
);
}Listing 16.2 Aktion zur Generierung der Statistiken
Die Methoden in der sechsten bis neunten Zeile, die die eigentlichen Graphiken generieren, geben den Pfad zu dem generierten Graphen zurück, der dann in einen relativen Pfad umgewandelt wird und dann im Template verwendet werden kann. Das Template statistics.ezt wird mit den Pfaden zu den generierten Graphiken aufgerufen.
Mit der Graph-Komponente ist es möglich, die Graphiken nicht nur in eine Datei, sondern auch dem Besucher direkt auszugeben. In diesem Fall könnte eine eigene Aktion für die direkte Ausgabe eines jeden Graphiken geschrieben werden. Jedoch kann die Graphik-Generierung, im Verhältnis zu anderen Prozessen bei der Erzeugung der Ausgabe einer Webseite, relativ lange dauern, weswegen hierfür stets ein statischer Cache verwendet werden sollte. Der einfachste statische Cache ist das direkte Speichern der generierten Grafik in ein durch den Webserver zugreifbares Verzeichnis.
Wie zuvor erwähnt, werden in der Beispielapplikation primär SVG-Diagramme erzeugt; die Ausgabe im Template verwendet entsprechend das HTML-Element <object>.
{use $graphs, $base}
<h3>Statistics</h3>
{foreach $graphs as $graph}
<object data="{$graph}" width="500" height="200">
Your browser can not display SVG.
</object>
{/foreach}Listing 16.3 Template für Statistiken
Die Syntax der Templates wurde im Detail in Kapitel 8, »Template«, erklärt. Das <object>-Element lässt sich wie das <img>-Element für Graphiken verwenden. Der eingeschlossene Text wird angezeigt, falls der Browser diese Graphik nicht anzeigen kann. Er könnte dabei Hinweise auf aktualisierte Versionen des Browsers oder notwendige Plug-ins enthalten.
Da der Internet Explorer den standardkonformen Weg der Einbettung über <object> nicht unterstützt, gibt es noch zwei weitere Möglichkeiten der Einbettung. Ein <iframe> mit dem SVG als Ziel funktioniert in jedem Browser, lässt sich aber nicht immer akzeptabel formatieren. Die direkte Einbettung im Internet Explorer funktioniert über das <embed>-Element, sodass Sie folgenden HTML-Code verwenden können.
<!--[if IE]>
<embed ... />
<![endif]-->
<!--[if !IE]-->
<object ... />
<!--[endif]-->Listing 16.4 <embed> für Internet Explorer
Der Internet Explorer wird das <embed>-Element verwenden. Andere Browser werden dieses invalide Element als Kommentar ignorieren. Um das Beispiel einfach zu halten, wird darin auf das zusätzliche Element verzichtet. Falls Sie die Anwendung unbedingt mit dem Internet Explorer testen wollen, sollten sie das Template entsprechend erweitern.
16.2.2 Einfaches Pie-Chart 

Ein einfaches Diagramm aus vorhandenen Daten können Sie mit Hilfe von nur drei Zeilen Code erstellen. Die in diesem Fall verwendeten Standardeinstellungen verwenden die Farben aus dem Tango-Projekt. Achsen und Skalierungen in Linien- und Balkendiagrammen werden automatisch an die übergebenen Daten angepasst.
protected static function generateBrowserStatistics()
{
$db = ezcDbInstance::get();
// SELECT browser, COUNT( * ) FROM access GROUP BY browser;
$query = $db->createSelectQuery();
$query->select( 'browser', 'COUNT( * )' )
->from( 'access' )
->groupBy( 'browser' );
$statement = $query->prepare();
$statement->execute();
$graph = new ezcGraphPieChart();
$graph->title = 'Browser statistics';
$graph->data['browsers'] =
new ezcGraphDatabaseDataSet( $statement );
$graph->render(
500, 200,
$path = self::$imagePath . 'browsers.svg'
);
return $path;
}Listing 16.5 Einfaches Tortendiagramm über Browser-Statistiken
Zuerst wird die Abfrage erstellt und ausgeführt, welche die darzustellenden Daten aus der Datenbank holt. Dazu wird die in Kapitel 6, »Datenbankanbindung«, vorgestellte Datenbankkomponente verwendet. Die Abfrage liefert die Anzahl der festgehaltenen Zugriffe gruppiert nach dem verwendeten Browser.
Um das eigentliche Diagramm zu erstellen, wird ein Objekt der Klasse ezcGraphPieChart instanziiert. Für andere Diagrammtypen muss lediglich dieser Konstruktor modifiziert werden. Die sonstige Verwendung ist bei allen Diagrammen gleich, ausgenommen davon sind einige strukturell bedingte Unterschiede. Jeder Diagrammtyp stellt eine Menge typspezifischer Optionen zur Verfügung, die nicht immer für alle Diagrammtypen verfügbar sind. Hinzu kommt, dass ein Tortendiagramm im Gegensatz zu den anderen Diagrammtypen nur einen Datensatz darstellen kann.
Das Setzen des Diagrammtitels in der auf den Konstruktor folgenden Zeile ist optional. Falls kein Titel angegeben wird, wird der Platz für das Diagramm verwendet. In dem Beispiel wird der Titel gesetzt, um das Diagramm in der Vollansicht eindeutig zu identifizieren.
Datensätze werden der Eigenschaft $data des Diagramm-Objekts hinzugefügt, wobei der Array-Schlüssel den Namen des Datensatzes definiert, unter dem sich der Datensatz später auch in der Legende des Diagramms finden wird. Als Datensätze hinzugefügt werden können alle Objekte, die von der abstrakten Klasse ezcGraphDataSet ableiten.
Im obigen Beispiel wird ein Objekt der Klasse ezcGraphDatabaseDataSet hinzugefügt, die im ezcGraphDatabaseTiein definiert ist, um direkt Resultate von Datenbankabfragen zu visualisieren. Andere mögliche Klassen für Datensätze werden später in diesem Kapitel vorgestellt. Ohne weitere Angaben verwendet ezcGraphDatabaseDataSet die erste Spalte des Datenbankergebnisses als Schlüssel und die zweite Spalte als Wert.
Abschließend muss das Diagramm nur noch ausgegeben werden. Der Methode render() werden dazu die Ausmaße und die Zieldatei angegeben, in die das Diagramm ausgegeben werden soll. Falls das Diagramm direkt an den Benutzer ausgegeben werden soll, kann die Methode renderToOutput() verwendet werden, die lediglich die Ausmaße übergeben bekommt und das Resultat direkt ausgibt. So wird der Pfad zum generierten Graphen zurückgegeben und anschließend auf der Statistikübersichtsseite angezeigt.
Abbildung 16.1 Einfaches Tortendiagramm
16.2.3 Dreidimensional 

Wie zuvor erwähnt, ist es nicht nur möglich, einfache zweidimensionale Diagramme zu erstellen, sondern auch schönere dreidimensionale Varianten. Das Diagramm mit der Übersicht derjenigen Betriebssysteme, mit denen das Blog besucht wurde, wird dementsprechend modifiziert.
protected static function generateOSStatistics()
{
// SELECT os, COUNT( * ) FROM access GROUP BY os;
// ...
$graph = new ezcGraphPieChart();
$graph->title = 'OS statistics';
$graph->legend = false;
$graph->palette = new ezcGraphPaletteEzBlue();Listing 16.6 Kopf für Betriebssystemstatistiken
Die Abfrage selbst ist hier nicht gelistet, da sie für die Beschreibung der Graph-Komponente keine Bedeutung hat. Sie ähnelt aber stark der aus dem vorigen Beispiel. In der siebten Zeile wird die Legende deaktiviert, da eine Auflistung der Datensätze in einem Tortendiagramm dem Betrachter wenig Information bietet. Die Legende ist ebenso wie der Titel ein Objekt, das von der Klasse ezcGraphChartElement ableitet und neben der Deaktivierung viele Optionen zur gezielten Formatierung bietet, die später noch vorgestellt werden.
Anschließend wird dem Graphen eine Palette zugewiesen. Paletten enthalten Farb- und Schriftdefinitionen, die von allen Elementen des Graphen verwendet werden. Eigene Paletten können durch Ableitung von ezcGraphPalette definiert werden. Falls Farben nach der Zuweisung einer Palette an den Graphen für einzelne Graph-Elemente gesetzt werden, überschreiben sie die durch die Palette definierten Werte.
$graph->data['OS'] = new ezcGraphDatabaseDataSet(
$statement
);
$graph->data['OS']->highlight['Linux'] = true;Listing 16.7 Datenpunkt »Linux« highlighten
Datensätze besitzen eine Reihe von Eigenschaften. Neben Farbe und Symbol ist eine Eigenschaft $highlight, die je nach Diagrammtyp eine unterschiedliche Auswirkung hat, vorhanden. Diese Eigenschaft dient dazu, einen der Werte besonders hervorzuheben. In einem Tortendiagramm bedeutet dies, dass das entsprechende Tortenstück um eine konfigurierbare Distanz aus der Mitte hervorgezogen wird.
In dem Beispiel wird eine Eigenschaft auf einem Datenpunkt gesetzt. Falls der letzte Array-Schlüssel nicht verwendet wird, kann eine Eigenschaft auch für einen ganzen Datensatz gesetzt werden, wie das nächste Beispiel zur Anzeige der Zugriffe auf die einzelnen Blog-Einträge zeigt.
foreach ( $graph->data['OS'] as $os => $datapoint )
{
$graph->data['OS']->url[$os] = '/os_statistics/' . $os;
}Listing 16.8 URLs verknüpfen
Neben der Möglichkeit über ArrayAccess auf die Eigenschaften der Datensätze und -punkte zuzugreifen, implementieren die Datensätze auch das Interface Iterator, sodass über diese iteriert werden kann.
Wie der Codeabschnitt zeigt, existiert auch eine Eigenschaft $url, die verwendet werden kann, um einzelnen Datensätzen oder Datenpunkten einen Verweis zu assoziieren. Dieser kann später benutzt werden, um den Graphen durch den Besucher klickbar zu machen.
$graph->renderer = new ezcGraphRenderer3d();
// Add links to SVG
ezcGraphTools::linkSvgElements( $graph );
return $path;
}Listing 16.9 Abschluss der Graph-Generierung
Der Eigenschaft $renderer wird ein neuer dreidimensionaler Renderer zugewiesen, sodass Sie eine dreidimensionale Ansicht des Tortendiagramms erhalten. Der Aufruf der Methode linkSvgElements() aus der Klasse ezcGraphTools mit dem Diagramm sorgt dafür, dass das SVG-Dokument mit den vorher zugewiesenen Verweisen versehen wird, die durch Besucher anklickbar sind.
Dies funktioniert nicht nur mit SVGs, sondern auch mit den vom GD-Treiber generierten Bitmaps, in deren Fall dann eine Image-Map zurückgeben wird, die in den HTML-Code der Ausgabe eingebunden werden kann. Auf Wunsch kann dieser Vorgang auch manuell erfolgen, da der Renderer Zugriff auf die Diagrammelemente hat, assoziiert mit ihrer Darstellung über die Methode getElementReferences(). Die Art der Assoziation ist abhängig vom Treiber: Im Fall von SVG ist es die ID des XML-Elements, und im Falle des GD-Treibers sind es die Eckpunkte eines umfassenden Polygons. Genaueres dazu findet sich in der Dokumentation. [http://ezcomponents.org/docs/api/latest/Graph/ezcGraphRenderer.html ]
Abbildung 16.2 Dreidimensionales Tortendiagramm
Jeder der Renderer stellt viele Optionen zur Verfügung, um das Erscheinungsbild des Diagramms abseits der verwendeten Palette zu modifizieren. Eine vollständige Liste der Optionen findet sich in der API-Dokumentation. [http://ezcomponents.org/docs/api/latest/Graph/ezcGraphRenderer3dOptions.html ]
$graph->renderer = new ezcGraphRenderer3d(); $graph->renderer->options->pieChartGleam = .3; $graph->renderer->options->pieChartGleamColor = '#FFFFFF'; $graph->renderer->options->pieChartShadowSize = 5; $graph->renderer->options->pieChartShadowColor = '#000000'; $graph->renderer->options->pieChartSymbolColor = '#55575388'; $graph->renderer->options->pieChartHeight = 5; $graph->renderer->options->dataBorder = 0;
Listing 16.10 Ausgabe verschönern
Die beiden ersten Optionen, die hier verwendet werden, definieren Intensität und Farbe eines Glanzes auf dem Tortendiagramm. Anschließend werden Größe und Farbe des Schattens gesetzt sowie die Farbe des Symbols (die Verbindungslinie zwischen Beschriftung und Tortenstück) definiert. Die Graph-Komponente akzeptiert für alle Farbangaben RGBA-Farben, also als optionalen vierten Anteil die Transparenz der Farbe.
In den letzten beiden Optionen wird die Höhe des Graphen gesetzt und der dunkle Rand in der letzten Ausgabe entfernt. Das Resultat kann sich sehen lassen.
Abbildung 16.3 Verbessertes, dreidimensionales Tortendiagramm
16.2.4 Eigene Palette definieren 

Für die Verwendung in der eigenen Applikation ist es von zentraler Bedeutung, dass sich die Diagramme dem Farbschema Ihrer Corporate Identity anpassen. Dazu können Sie eine eigene Palette definieren.
class gpBlogPalette extends ezcGraphPalette
{
protected $axisColor = '#34362e';
protected $majorGridColor = '#34362eBB';
protected $dataSetColor = array(
'#55575330',
'#888a8530',
'#babdb630',
'#d3d7cf30',
);
protected $dataSetSymbol = array(
ezcGraph::BULLET,
);
protected $fontName = 'serif';
protected $fontColor = '#555753';
}Listing 16.11 Eigene Palette definieren
Ein vollständige Liste der Eigenschaften von Paletten findet sich in der API-Dokumentation. [http://ezcomponents.org/docs/api/latest/Graph/ezcGraphPalette.html ] In diesem Beispiel werden Farben für die Achsen und das grobe Gitter gesetzt, das erst im nächsten Beispiel (ein Liniendiagramm) zu sehen sein wird. Danach wird eine Liste von Farben definiert, die alternierend für die Datenpunkte in Tortendiagrammen beziehungsweise für Datensätze in den anderen Diagrammtypen verwendet werden. Auch hier können natürlich transparente Farben verwendet werden, was die Tortenstücke durchscheinend aussehen lässt. Ebenso wie eine Liste von Farben angegeben werden kann, kann auch eine Liste der verwendeten Symbole angegeben werden. Diese Symbole werden sowohl in der Legende verwendet als auch als Markierungen in Liniendiagrammen oder als Grundfläche für dreidimensionale Balkendiagramme. Zum Ende werden Schriftart und Farbe definiert. Unter Verwendung der Palette erscheint das Diagramm nun in einem neuen Gewand.
Abbildung 16.4 Verwendung der eigenen Palette
16.2.5 Liniendiagramm erstellen 

Das Liniendiagramm, das als drittes und letztes Diagramm die Statistikseite vervollständigen soll, wird die Anzahl der Besuche für jeden einzelnen Blog-Eintrag zeigen. Durch diese Daten soll eine interpolierende Kurve gelegt werden, die eventuelle Entwicklungen der Besucherzahlen aufzeigt.
protected static function generateHitStatistics()
{
// SELECT data, COUNT(*)
// FROM access
// WHERE type='blog' GROUP BY data ORDER BY data;
$graph = new ezcGraphLineChart();
$graph->title = 'Blog posting hits';
$graph->palette = new gpBlogPalette();
$graph->xAxis = new ezcGraphChartElementNumericAxis();Listing 16.12 Hit-Statistik erstellen
Die genaue Abfrage ist erneut von geringer Relevanz. Wie üblich werden Titel und Palette gesetzt, wobei wir hier natürlich erneut die zuvor selbst definierte Palette verwenden.
Die Graph-Komponente kennt verschiedene Typen von Achsen. Da die Werte in der abgefragten Spalte data numerisch sind genau wie die Anzahl der Besuche zu diesem Blog-Eintrag, wird auch für die X-Achse eine numerische Achse verwendet. Standardmäßig wird eine Achse verwendet, die auf die Anzeige von Zeichenketten optimiert ist, da sich in PHP alle möglichen Werte immer als Zeichenketten auffassen lassen.
Für beide Achsen kann der Typ beliebig gesetzt werden. Andere verfügbare Achsen sind eine numerische Achse mit logarithmischer Skalierung sowie eine Achse optimiert auf die Anzeige von Zeitpunkten und Zeiträumen. Auch wenn alle Achsen versuchen, optimale Werte für Skalierungen und Intervalle zu ermitteln, mag das nicht immer den Ansprüchen gerecht werden, weswegen jede dieser Eigenschaften konfigurierbar ist.
$graph->data['hits'] = new ezcGraphDatabaseDataSet(
$statement
);
$graph->data['average'] = new ezcGraphDataSetAveragePolynom(
$graph->data['hits'],
3
);
$graph->data['average']->symbol = ezcGraph::NO_SYMBOL;Listing 16.13 Zweiten Datensatz hinzufügen
In diesem Beispiel wird dem Diagramm ein weiterer Datensatz hinzugefügt. Im Gegensatz zu Tortendiagrammen ist das bei allen anderen Diagrammtypen problemlos möglich.
Datensätze der Klasse ezcGraphDataSetAveragePolynom akzeptieren einen anderen Datensatz und einen maximalen Grad für das Interpolationspolynom als Eingabe. Mittels der Methode der kleinsten Quadrate [http://de.wikipedia.org/wiki/Methode_der_kleinsten_Quadrate ] wird ein Polygon des angegebenen Grades gefunden, das die Punkte interpoliert.
$graph->options->fillLines = 230;
$graph->render(
500, 200,
$path = self::$imagePath . 'hits.svg'
);
return $path;
}Listing 16.14 Graph rendern
Auch der Graph insgesamt kennt Optionen, die Daten und Ausgabe beeinflussen. So lässt sich bei Tortendiagrammen die Beschriftung der Tortenstücke anpassen oder wie in diesem Fall definieren, dass die Zwischenräume zwischen Achse und Linie transparent gefüllt werden.
Abbildung 16.5 Liniendiagramm der Zugriffe mit Durchschnittsfunktion
16.2.6 Formatierung der Elemente 

Wie bereits erwähnt, können die einzelnen Diagrammelemente einzeln formatiert werden, so auch der Hintergrund eines Diagramms. Optionen, die immer zur Verfügung stehen, sind die aus CSS bekannten Eigenschaften margin und padding sowie die Hintergrundfarbe und die Rahmenfarbe.
$graph->background->borderWidth = 2;
$graph->background->border = '#2e343680';
$graph->background->padding = 2;
$graph->background->image =
dirname( __FILE__ ) . '/../../docs/ez.png';
$graph->background->repeat = ezcGraph::NO_REPEAT;
$graph->background->position = ezcGraph::BOTTOM | ezcGraph::LEFT;Listing 16.15 Graph-Elemente konfigurieren
Hintergrundbilder lassen sich genau wie in CSS horizontal, vertikal oder in beide Richtungen wiederholen und ähnlich positionieren.
Auch wenn Bitmap-Graphiken in SVG-Dateien normalerweise nur referenziert werden, lassen sie sich über eine data-URL, die den MIME-Type der Datei sowie den base64-codierten Inhalt enthält, direkt in eine SVG-Datei einbinden. Demnach muss das Bild, das als Hintergrund verwendet wird, nicht für den Besucher durch den Webserver erreichbar sein. Zur Erinnerung: Diese Einbettung von Bildern funktioniert momentan noch nicht mit dem Flash-Treiber; alle anderen Funktionen sind mit allen Treibern verfügbar.
Abbildung 16.6 Formatierung einiger Graph-Elemente










Ihre Meinung






