Thema: Webentwicklung

Einmal T3Blog bitte – ein Selbstversuch mit der Typo3 Extension von Snowflake.ch

22. Oktober 2009

Snowflake.chDie Erweiterung T3Blog ist eine relativ neue Typo3 Erweiterung der schweizer Firma Snowflake. Soviel vorab, T3Blog ist für Typo3 Verhältnisse zweifelsfrei schon eine recht komfortable Bloganwendung, das liegt vor allem an der für Typo3 Verhältnisse recht aufgeräumten Administrationsoberfläche des Plugins. Allerdings hat auch die getestete Version 0.6.2 noch einige Kinderkrankheiten. Ein Selbstversuch.

Die Installation

Die Ausgangssituation: Typo3 Version 4.2.10, TemplaVoila basierte Seite, T3Blog in der Version 0.6.2. Nachdem ich die erforderlichen Erweiterungen typoscripttools und sfpantispam installiert hatte, lud ich die Erweiterung t3blog, auf die Erweiterung DAM (dam_1.1.1.t3x) hatte ich zunächst verzichtet. Das Manual sagt:

The extension is configured to work smoothly with the DAM. You can use it without DAM – but then you will have to reprogramm quite a few lines of TypoScript and PHP-Code.

Die Folge – nicht nur die Installation scheiterte, Typo3 ließ sich gar nicht mehr starten, stattdessen ein Fatal Error, dass eine DAM Methode nicht zu finden war, nicht gerade dass, was ich erwartet hatte. Konsequenz, den Ordner T3Blog löschen (was unter Windows XP auch noch einen Neustart erfordert, anderenfalls kann die .ttf Datei nicht entfernt werden), die temp Version unter typo3conf entfernen, DAM und t3blog erneut installieren. Ohne DAM Erweiterung sollte man es also gar nicht erst versuchen.

Die dann folgende Einbindung schien zunächst kein Problem. Dem User Manual folgend habe ich zuerst eine neue Seite angelegt (Typ Standard), und unter “Enthält Plugin” das Plugin “T3BLOG plugin” eingefügt.
Im zweiten Schritt habe ich auf dieser Seite ein neues Template angelegt und dort die erforderlichen Extensions eingebunden: “T3BLOG main configuration (t3blog)” und “T3BLOG functionalities on your website”. Auf die Erweiterungen “T3BLOG template – snowflake theme 1″ und “T3BLOG CSS – snowflake theme 1″ habe ich verzichtet, meine Idee war es, die Funktionalitäten ausschließlich über die vorhandenen Widgets zu realisieren. Um diese Idee zu testen, habe ich eine Kategorie unter T3BLOG > Kategorien angelegt und einen ersten Beitrag geschrieben. Auf der Blogseite das Plugin “blogList” als Content Element einfügt, und mir das Resultat angesehen.

Alle Einträge kommen doppelt

Der Blick auf die Vorschau – die nächste Irritation, die Einträge kamen doppelt, einmal – wie gewünscht – über das Plugin, aber auch als normales Content Element in meinem Kopfbereich, ich ging auf die Suche. Mit diesem Problem war ich wohl nicht allein. Das Konzept, dass sich ein Blogeintrag aus normalen Content Elementen zusammensetzt ist im Prinzip gar nicht schlecht und lässt beim Schreiben viele Freiheiten, gleichzeitig führt es aber zu der Dopplung aller Inhalte, insbesonders wenn TemplaVoila im Spiel ist. Die Lösungsansätze sind aber nicht gerade befriedigend. Der Vorschlag den entsprechenden Bereich einfach mittels CSS auszublenden ist sicher keine echte Lösung und der Vorschlag das ganze via TypoScript hart zu verlinken ist auch nicht der Weisheit letzter Schluss. Es musste doch noch eine einfachere Lösung geben diese Dopplung loszuwerden, ohne eine Template Kopie, ohne feste Verdrahtung. Erst ein Kommentar bei dem Artikel von Joachim Weinbrenner half weiter. Die Lösung besteht aus wenigen Zeilen Typoscript code, die direkt in das DO des Templates eingebunden werden (dort wo die doppelten Einträge erscheinen):

10 = RECORDS
10 {
	source.current = 1
	tables = tt_content
	conf.tt_content.stdWrap.if.isFalse.field = irre_parentid
}

Es werden keine Tags angezeigt

Nachdem diese ersten Hürden beseitigt waren, band ich als nächstes die anderen Widgets ein, alles lief – nur das Widget TagCloud wollte nicht, es blieb einfach leer. Ein Blick in die setup.txt des Widgets half auch nicht weiter, die Anzahl an an gleichen Tags zu erhöhen war ebenso erfolglos. Aber auch hier konnte das am Ende das Netz weiterhelfen – bei der Knowlegdebase der Universität Konstanz wurde ich fündig, es darf keine Einträge ohne Tags geben, dann entsteht ein SQL Fehler und die Cloud bleibt leer – also wirklich bei jedem Eintrag Tags einpflegen, dann funktioniert das Widget auch.
Zweites Problem, die TagCloud kommt per default mit Inlinestyles – eigentlich unverständlich – um das dauerhaft abzuschalten sollte man den PHP Code direkt verändern. Da ich ohnehin gerade im PHP Code gelandet war, habe ich die Sortierung der Tags so verändert, dass sich diese nun auch alphabetisch sortieren lassen.

// Zeile 216 auskommentieren,
// sonst wird immer ueber
// die Anzahl sortiert
//uasort($_tags, 'sortByCountValue');

Das RSS Widget

Als nächstes fügte ich dass RSS-Widget ein. Das Widget schreibt die Verweise für rss 0.91 und 2.0, ich klickte auf den Verweis – und anstelle der Verweise erschien der gesamte RSS-Code – nicht gerade dass, was ich erwartet hatte. Also gut, gemäß einer gefundenen Anleitung ergänzte ich den Typoscript Code des Templates, aber auch das brachte zunächst keine Veränderung. Mein Problem lag darin, dass ich simulateStaticDocuments aktiviert hatte -

Das RSS Widget einfach in die existente Blogseite integrieren, um dort die entsprechenden Verweise anzeigen zu können ist wohl nicht der richtige Weg. Das Widget generiert das RSS und die entsprechenden Verweise, aber öffnet man den Verweis, so erscheint die Blogseite und an der Stelle des Widgets der gesamte RSS Code. Wohl eher ein Anwenderfehler als etwas, was man der Software ankreiden sollte, also zweiter Versuch, diesmal seperate Seite, nur das RSS eingebunden.

Chaotische Inhalte

Soweit vorgedrungen fing ich an echte Inhalte in den Blog zu pflegen, aus einfachen Lorem Ipsum Einträgen wurden reale Posts, die z.T. aus vielen einzelnen Content Elementen bestanden. Ein Blick auf die Ausgabe, und ich stand vor der nächsten Hürde, die einzelnen Content Elemente waren zwar dem richtigen Eintrag zugeordnet, aber entsprachen nicht der eingepflegten Reihenfolge, zunächst dachte ich an einen Eingabefehler, sortierte um, gab den nächsten Eintrag ein, und wieder waren alle alten Einträge im chaotischem Zustand. Die nächste Recherche – auch hier liegt das Übel im mangelhaften Zusammenspiel zwischen T3blog und TemplaVoila.
TemplaVoila nutzt zur Sortierung eben nicht das Feld sorting – daher das entstandene Chaos. Johannes Dörr beschreibt in seinem Blog einen Workaround, der dieses Problem behebt. Allerdings erzwingt diese Lösung eine Änderung in einer TemplaVoila PHP Klasse, was für künftige Updates sicher nicht der optimale Weg ist. Aber – um mit Napoleon zu sprechen – Wenn man schon dummes tut, dann sollte es wenigstens funktionieren – jetzt sollte dieser Blog endlich vernünftig laufen. Habe die Änderungen vorgenommen, und das Chaos innerhalb der Blogeinträge hatte ein Ende.

function correctSortingAndColposFieldsForPage($flexformXML, $pid) {
  // Ergaenzung - disable recording...
  require_once(PATH_t3lib . 'class.t3lib_page.php');
  require_once(PATH_t3lib . 'class.t3lib_tsparser_ext.php');
  $sysPageObj = t3lib_div::makeInstance('t3lib_pageSelect');
  $rootLine = $sysPageObj->getRootLine($pid);
  $TSObj = t3lib_div::makeInstance('t3lib_tsparser_ext');
  $TSObj->tt_track = 0;
  $TSObj->init();
  $TSObj->runThroughTemplates($rootLine);
  $TSObj->generateConfig();
  $arr = split(
    ',',
    $TSObj->setup['config.']['tx_templavoila.' ['disableReordering']
  );
  if (in_array($pid , $arr)) {
    return;
  }
  // Ende der Ergaenzung
  [... urspruenglicher Methodeninhalt]
}

Die Erweiterung der Funktion schaltet – abhängig von einem gesetzten config Wert, die Sortierung in TemplaVoila ab – es muss also noch per typoscript der entsprechende Wert gesetzt werden.

#der wert entspricht der blogseite
config.tx_templavoila.disableReordering = 15

Die Artikelnavigation läuft nicht…

Drei, vier, fünf Einträge eingestellt, und das nächste Problem. Die Artikelnavigation (nächster Artikel, vorheriger Artikel, zur Übersicht) funktioniert nicht richtig. Bei den ersten Einträgen ist noch alles in Ordnung, aber bei Einträgen, die nicht auf der ersten Seite liegen, werden die Navigation gar nicht angezeigt.
Der Fehler entsteht bei der Zusammensetzen eines Verweises für die Detailansicht, es fehlt der Parameter tx_t3blog_post_pointer. Dieser Parameter enthält die aktuelle Seitenlaufnummer, und wird beim Zusammensetzen der SQL Anfrage als Berechnungsgrundlage für das LIMIT genutzt. Eigentlich kein Problem – die entsprechenden Zeilen im Typoscript werden um die folgende Angabe ergänzt:

#Ergaenzung um den Parameter der Seitenlaufnummer
&tx_t3blog_post_pointer={GPvar:tx_t3blog_post_pointer}

Aber wie sieht es mit den Verweisen für den Permalink und dem Trackbacklink aus? – Hier die Seitenzahl mitzulieferen wäre Blödsinn, sie ändert sich mit jedem neuen Artikel, und lässt man den Parameter weg, so erscheint die Artikelnavigation nicht. Es half nichts, wenn die Artikel-Navigation sauber funktionieren sollte, musste die Funktion umgeschrieben werden. Die geänderte Methode getSingleNavigation kommt ohne Pointer aus, stellt nur eine Abfrage an die Datenbank und das Ergebnis muß zudem auch durch keine PHP-Schleife geleitet werden, um die korrekten Einträge zu finden – durchaus ein Gewinn – auch wenn diese Syntax so nur mit MySQL funktioniert:

function getSingleNavigation($current)	{
    include_once('class.listFunctions.php');
    // das sql statement mit subselects fuer previous und next
    $sql = 'SELECT uid,title,@a:=date ,
    ( SELECT CONCAT_WS( \'|\',uid,title,crdate )
      FROM tx_t3blog_post
      WHERE date < @a
      ORDER BY date DESC
      LIMIT 1
    ) AS previous,
    ( SELECT CONCAT_WS( \'|\',uid,title,crdate )
      FROM tx_t3blog_post
      WHERE date > @a
      ORDER BY date ASC LIMIT 1
    ) AS next
    FROM tx_t3blog_post
    WHERE uid='.$current;
 
  // datenbank abfrage...
  $RES = $GLOBALS['TYPO3_DB']->sql(TYPO3_db,$sql);
  $singeNavigationItems = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($RES);
 
  //schreiben der verweise, inhaltlich aendert sich hier nicht mehr viel..
  if(!empty($singeNavigationItems['previous'])) {
    // trennen der ermittelten previous eigenschaften
    $temp = explode('|',$singeNavigationItems['previous']);
    // ab hier wie vorab
    $title = $temp[1];
  	if(strlen($title)>28){
  		$title = substr($title,0,25).'...';
  	}
    $data['previous'] = $this->getTitleLinked(
      $title, $temp[0], $temp[2], 'singleNavTitleLink',$temp[1]
    );
  }
  if(!empty($singeNavigationItems['next'])) {
    // trennen der ermittelten previous eigenschaften
    $temp = explode('|',$singeNavigationItems['next']);
    // ab hier wie vorab
    $title = $temp[1];
  	if(strlen($title)>28){
  		$title = substr($title,0,25).'...';
  	}
    $data['next'] = $this->getTitleLinked(
      $title, $temp[0], $temp[2], 'singleNavTitleLink',$temp[1]
    );
  }
  $data['backId'] = t3blog_div::getBlogPid();
  $data['backText'] = $this->pi_getLL('backText');
	//schreiben der navigation...
  return t3blog_div::getSingle($data, 'singleNavigation');
}

Und so klappt es dann auch mit den Nachbarn – egal auf welcher virtuellen Seite sich der Eintrag befindet.

Fazit

Die Tatsache, dass sich fast alle Bestandteile des Blogs über Typoscript ändern bzw. konfigurieren lassen ist gar nicht schlecht, aber nichts für Einsteiger. Zumindest eine Flexform-Maske für die Basiseinstellungen (bspw. Anzahl von Einträgen auf einer Seite, Anzeige Captcha, Tags usw.) würde den Komfort noch deutlich erhöhen. Schade ist auch, dass die Widget / Typoscript Idee dann eben doch nicht vollständig durchgehalten wurde. So hatte ich vor, die bereits erwähnte Artikelnavigation von oben nach unten zu verlegen, ging nicht – SingleNavigation und Artikel werden in der PHP Klasse zusammengezogen, arbeitete ich mit dem ###MORE### Platzhalter, um auf der Übersicht die Länge des Artikels einzugrenzen, so fand ich ein <br /> der Text und Verweis trennte – auch hier half nur ein Eingriff auf PHP Ebene.
Erstaunlich fand ich, dass keine Möglichkeit vorgesehen war, sich die Tags eines Eintrages ausgeben zu lassen, es wurden ausschließlich die Kategorien genutzt. Die mangelhafte Logik zur Ermittlung von vorherigen und nächsten Einträgen ebenso.
Auf die Unverträglichkeit mit TemplaVoila sollte dann doch explizit hingewiesen werden, damit man in einem solchen Typo3 Szenario lieber eine andere Alternative sucht.
Mir persönlich gefällt die JavaScript-Lastigkeit einiger Widgets nicht (z.B. das Artikel Archiv), allerdings ließen sich diese Dinge recht einfach beseitigen.
Eine Konkurenz zu ausgewachsenen Blogsystemen wie Wordpress ist T3Blog, oder andere Blog Extensions wie bspw. timtab aber noch lange nicht. Für den professionellen Bereich ist daher eine Kombination verschiedener Systeme sicher vorzuziehen.

Sie können diesen Befehl jetzt nicht ausführen

08. September 2009

Sie können diesen Befehl jetzt nicht ausführen
Immer wenn es schnell gehen muß – für ein Projekt hatte ich eine stored procedure angelegt, und auf der Konsole getestet. Alles wunderbar, aber – eingebunden in ein PHP Script bricht das Ganze mit der Meldung ab: “You can’t run this command now” – ich will aber, also wo war der Fehler?

In einer gespeicherten Prozedur können ganze Abläufe von Anweisungen unter einem Namen gespeichert werden, die dann auf dem Datenbankserver zur Verfügung stehen und ausgeführt werden können. Sie ist somit ein eigenständiger Befehl, der eine Abfolge von gespeicherten Befehlen ausführt. Solche Routinen können viel Logik in die Datenbank auslagern und sind gerade bei sich ständig wiederholenden Aufgaben äußerst hilfreich.
Zurück zum Problem – die Prozedur lief auf der Konsole einwandfrei, aber über das PHP Script war nichts zu machen. Die folgenden Zeilen dienen lediglich der Veranschaulichung des Problems, mit dem eigentlichen Skript hat dieser Code-Schnipsel nichts zu tun:

$mysqli = new MySQLI('host','user','pass','db');
$result = $mysqli->query("CALL myprocedure()");
$data = $result->fetch_assoc();
$result2 = $mysqli->query("SELECT something DIFFERENT");

Ein solcher Aufruf schlägt fehl. Wahlweise man erhält den Fehler: “Lost connection to MySQL server during query“. Oder – für den Fall, dass man kein free auf das Ergebnis ($result) anwendet – eben “Commands out of sync; you can’t run this command now“. Der Grund: Eine stored procedure liefert nicht ein Ergebnis, sondern zwei – das Resultset zum einen und zum anderen eine Statusmeldung. Auch wenn es mich in dem Moment geärgert hat, der Fehler macht Sinn – sobald man sich das nächste Ergbnis abholen will, geht es nicht weiter, es hängt einfach noch ein Ergebnis in der Warteschleife (die Statusmeldung), jeder weitere REQUEST muß scheitern. Die Lösung: Anstatt $mysqli->query die Funktion $mysqli->multi_query verwenden:

$mysqli = new MySQLI('host','user','pass','db');
if($query = $mysqli->multi_query("CALL myprocedure()") {
  $result = $mysqli->use_result();
  $data = $result->fetch_assoc();
  $result->free();
  while ($mysqli->next_result()) {
    $result = $mysqli->use_result();
    if ($result instanceof mysqli_result) {
      $result->free();
   }
 }
}
$result2 = $mysqli->query("SELECT something DIFFERENT");

Diese Variante tat es für mich, und das Script lief wie gewünscht. Nachträglich bin ich dann noch auf einen Artikel gestoßen, der eben dieses “Phänomen” ausführlich beschreibt und neben der hier beschriebenen Lösung auch noch eine zweite Alternative anbietet – die Verwendung des statischen Aufrufes von MySQLI::query(). Manchmal bräuchte man halt nur die notwendige Ruhe und die richtigen Suchbegriffe.

Seite 11 von 11Anfang...7891011