{"id":728,"date":"2011-11-17T17:21:04","date_gmt":"2011-11-17T16:21:04","guid":{"rendered":"https:\/\/sgaul.de\/?p=728"},"modified":"2014-03-13T21:34:53","modified_gmt":"2014-03-13T20:34:53","slug":"grose-datenmengen-mit-extbase-verarbeiten","status":"publish","type":"post","link":"https:\/\/sgaul.de\/2011\/11\/17\/grose-datenmengen-mit-extbase-verarbeiten\/","title":{"rendered":"Gro\u00dfe Datenmengen mit Extbase verarbeiten"},"content":{"rendered":"

Extbase ist an sich eine sch\u00f6ne Sache: Man kann mit relativ geringem Aufwand auch komplexe Anwendungen schreiben. Ein gro\u00dfes Problem ist jedoch die Effizienz. Das vollst\u00e4ndige Auslesen von Objekten aus einer Datenbank in ein Array, um diese nachfolgend zu bearbeiten, ist speicherintensiv und merklich langsam. M\u00f6chte man einfach eine lange Liste an Logs ausgeben, f\u00e4llt das besonders auf. Ich m\u00f6chte hier einen eleganten Weg zeigen, wie man m\u00f6glichst direkt jede Datenbankzeile in die Ausgabe schreibt.<\/p>\n

Das Ziel<\/h2>\n

Wir m\u00f6chten eine Liste von Logs im Browser anzeigen. Da Sortierung und Seiteneinteilung von Javascript \u00fcbernommen werden, m\u00f6chten wir direkt 1000 Zeilen der Datenbanktabelle in die HTML-Tabelle \u00fcbertragen. Die Tabelle soll dabei m\u00f6glichst schnell ausgeliefert werden.<\/p>\n

Der Ablaufplan<\/h2>\n
\r\n  \r\n    \r\n    \r\n    \r\n      \r\n    <\/marker>\r\n    \r\n      \r\n    <\/marker>\r\n    \r\n      \r\n    <\/marker>\r\n    \r\n    \r\n    \r\n    \r\n    \r\n    \r\n    \r\n    \r\n    \r\n    \r\n    \r\n    \r\n    \r\n    \r\n    \r\n    \r\n      \r\n      \r\n    <\/linearGradient>\r\n    \r\n      \r\n      \r\n    <\/linearGradient>\r\n    \r\n      \r\n      \r\n    <\/linearGradient>\r\n    \r\n      \r\n      \r\n    <\/linearGradient>\r\n    \r\n      \r\n      \r\n    <\/linearGradient>\r\n    \r\n      \r\n      \r\n    <\/linearGradient>\r\n    \r\n      \r\n      \r\n    <\/linearGradient>\r\n    \r\n      \r\n      \r\n    <\/linearGradient>\r\n    \r\n      \r\n      \r\n    <\/linearGradient>\r\n    \r\n      \r\n      \r\n    <\/linearGradient>\r\n    \r\n      \r\n      \r\n    <\/linearGradient>\r\n    \r\n  <\/defs>\r\n  \r\n  \r\n    \r\n      \r\n        image\/svg+xml<\/dc:format>\r\n        \r\n        <\/dc:title>\r\n      <\/cc:Work>\r\n    <\/rdf:RDF>\r\n  <\/metadata>\r\n  \r\n    \r\n    Controller<\/tspan><\/text>\r\n    \r\n    Fluid-Template<\/tspan><\/text>\r\n    \r\n    ViewHelper<\/tspan><\/text>\r\n    \r\n    IteratorRepository<\/tspan><\/text>\r\n    \r\n    \r\n    Table Data<\/tspan><\/text>\r\n    \r\n    1<\/tspan><\/text>\r\n    \r\n    2<\/tspan><\/text>\r\n    \r\n    4<\/tspan><\/text>\r\n    \r\n    5<\/tspan><\/text>\r\n    \r\n      \r\n        \r\n        \r\n        \r\n        \r\n        \r\n        \r\n        \r\n        \r\n        \r\n        \r\n        \r\n        \r\n        \r\n        \r\n        \r\n        \r\n      <\/g>\r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n      \r\n    <\/g>\r\n    \r\n    \r\n    \r\n    \r\n    \r\n    \r\n    Table Row<\/tspan><\/text>\r\n    \r\n    next()<\/tspan><\/text>\r\n    \r\n    3<\/tspan><\/text>\r\n  <\/g>\r\n<\/svg><\/pre>\n

Nichts zu sehen? Zur PNG-Version.<\/a>\n<\/p>\n

Hinweis:<\/em> Die Darstellung ist nicht ganz korrekt, da der Controller die gerenderten Daten des Templates zur\u00fcckbekommt und diese in Richtung Ausgabe weiterleitet. Vielen Dank an Alex f\u00fcr diesen Hinweis<\/a>.<\/p>\n

Der Controller<\/h3>\n

Der Controller verliert in diesem Ansatz die Aufgabe, irgendwelche Daten f\u00fcr die Log-Tabelle zu besorgen. Er muss lediglich das entsprechende Template aufrufen und ggf. andere Jobs erledigen, die neben der Tabelle auf der Seite zu sehen sind.<\/p>\n

Das Fluid-Template<\/h3>\n

Das Template gestaltet das Drum-Herum und ruft darin f\u00fcr die Log-Tabelle einen View-Helper auf. Zudem kann man als Inhalt des View-Helper-Tags ein Template vorgeben, in welchem der Helper nur Variablen ersetzen braucht. Hierf\u00fcr muss man den allgemeinen Teil von dem trennen, der mit jeder Zeile wiederholt werden muss. Ein simpler Ansatz w\u00e4re etwa:<\/p>\n

\r\n\t\r\n\t\t
ID<\/th>Inhalt<\/th><\/tr>\r\n\t\t\r\n\t\t\t
%1$d<\/td>%1$s<\/td><\/tr>\r\n\t\t<\/LogTable:forEachRow>\r\n\t<\/table>\r\n<\/my:LogTable><\/pre>\n

Das obige Variablenformat l\u00e4sst sich dann direkt mit PHPs Sprintf-Funktion<\/a> bef\u00fcllen.<\/p>\n

Der View-Helper<\/h3>\n

Dies ist die einzige Stelle, an der wie die kompletten Log-Daten zwischenspeichern. Daf\u00fcr aber gleich im fertigen Ausgabeformat, so dass wir sie nicht noch einmal durcharbeiten m\u00fcssen. Hierf\u00fcr nehmen wir eine Singleton-Instanz des Iterator-Repositorys, iterieren \u00fcber die einzelnen Zeilen der Datenbanktabelle und bef\u00fcllen hiermit jeweils unser Template. Am Ende geben wir den so zusammengebauten Ausgabestring zur\u00fcck.<\/p>\n

Das Iterator-Repository<\/h3>\n

Das Repository implementiert das PHP-Iterator-Interface<\/a>. Dies erlaubt es dem View-Helper, das Repository in einer Foreach-Schleife auszulesen. Der Rest ist relativ simpel: Beim Aufruf von rewind()<\/code> und dem Konstruktor wird ein Query abgesetzt, das Result speichern wir in einem Klassenattribut, um es in anderen Methoden nutzen zu k\u00f6nnen.<\/p>\n

$this->result = $GLOBALS['TYPO3_DB']->SELECTquery(\/*...*\/);<\/pre>\n

Hierbei sollte gleich darauf geachtet werden, dass m\u00f6glichst viel Logik direkt in SQL erledigt wird. So kann man beispielsweise Datumsformate direkt im Query definieren.
\nEin Aufruf von next() setzt ein Row-Attribut mittels<\/p>\n

$this->row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($this->result);<\/pre>\n

Zu guter Letzt muss ein current()<\/code> noch $this->row<\/code> oder eine angepasste Variante davon zur\u00fcckgeben.<\/p>\n

Fazit<\/h2>\n

Die vorgegebenen Code-Schnipsel dienen der Verdeutlichung und sind nicht vollst\u00e4ndig. Wenn man dem Ansatz jedoch folgt, kann man sehr direkt auf der Datenbank arbeiten, ohne die offizielle Vorgehensweise von Extbase wirklich zu verletzen.<\/p>\n","protected":false},"excerpt":{"rendered":"

Extbase ist an sich eine sch\u00f6ne Sache: Man kann mit relativ geringem Aufwand auch komplexe Anwendungen schreiben. Ein gro\u00dfes Problem ist jedoch die Effizienz. Das vollst\u00e4ndige Auslesen von Objekten aus einer Datenbank in ein Array, um diese nachfolgend zu bearbeiten, ist speicherintensiv und merklich langsam. M\u00f6chte man einfach eine lange Liste an Logs ausgeben, f\u00e4llt das besonders auf. Ich m\u00f6chte hier einen eleganten Weg zeigen, wie man m\u00f6glichst direkt jede Datenbankzeile in die Ausgabe schreibt.<\/p>\n","protected":false},"author":1,"featured_media":735,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[91],"tags":[245,238,239,174],"_links":{"self":[{"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/posts\/728"}],"collection":[{"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/comments?post=728"}],"version-history":[{"count":16,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/posts\/728\/revisions"}],"predecessor-version":[{"id":895,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/posts\/728\/revisions\/895"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/media\/735"}],"wp:attachment":[{"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/media?parent=728"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/categories?post=728"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/tags?post=728"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}