Einen Hook unter Typo3 programmieren
Veröffentlicht am 24.02.2010 | Kommentar schreiben | Tags: php, typo3
Wenn man eine Extension in Typo3 an seine eigenen Bedürfnisse anpassen möchte, ohne den Code direkt umzuprogrammieren, kommen die sogenannten Hooks ins Spiel. Der Artikel von Robert Lemke ist Grundlage dieser Beschreibung gewesen.
Was ist ein Hook?
Ein Zitat aus wikipedia besagt:
"In der Programmierung bezeichnet der Begriff Hook eine Schnittstelle, mit der fremder Programmcode in eine bestehende Anwendung integriert werden kann, um diese zu erweitern, deren Ablauf zu modifizieren oder um bestimmte Ereignisse abzufangen."
Mit einem Hook möchte man immer eine Sache erreichen: Den Code einer Extension zu erweitern, ohne Code direkt verändern zu müssen. In diesem Artikel wird primär darauf eingegangen vorhandene, in einer Extension explizit berücksichte, Hooks anzusprechen.
Eine eigene Extension erstellen
Zunächst ist es notwendig, dass man sich eine eigene Extension erstellt. Diese Extension ist natürlich nur dafür da, um einen Hook implementieren zu können. Als erstes wird die Extension "kickstarter" installiert. Unter dem Menüpunkt "Erw-Manager" ist nun im Drop-Down-Menü der Punkt "Create new extension" verfügbar. Dort vergibt man unter dem Menüpunkt "General info" einen Namen und ggf. eine Beschreibung der Extension. Unter "Enter extension key:" wird ein eindeutiger Extension-Key vergeben. Anschließend auf den Button "Update" und "View results" drücken. Dort steht nochmal eine kurze Zusammenfassung des darauf erzeugen Codes zur Verfügung. Abschließend auf "Write" drücken. Anschießend kann die Extension sofort installiert werden. Manuell müssen jetzt im Extensionverzeichnis die Dateien ext_localconf.php und ext_tables.php erstellt werden, dazu aber später mehr.
Zwei Arten von Hooks: callUserFunction und getUserObj
Es zwei mögliche Arten von Hooks, wobei diese sich größtenteils nur in ihrer Einbindung unterscheiden. Zunächst wird die callUserFunction betrachtet.
Hook als callUserFunction
Um die Verwendung eines Hooks über die callUserFunction zu demonstrieren wird als Beispiel die Extension "comments" gewählt. Ziel ist es die Extension so zu erweitern, dass jeder Kommentar über den Zusatz #comment-###UID### in der URL direkt angesprochen werden kann. Hierfür ist es notwendig, dass der Marker ###UID### mit der UID des jeweiligen Kommentars erweitert wird, damit im Template der Anker <a name="comment-###UID###"></a> hinzugefügt werden kann.
Hook Einbindung im Quelltext finden:
Zunächst muss der entsprechende Code im Extension Quelltext gefunden werden damit man die neue Funktion darauf entsprechend anpassen kann. Dafür welchet man zunächst in folgende Datei:
EXT:comments/pi1/class.tx_comments_pi1.php
In Zeile 411 befindet sich die Funktion comments_getComments(&$rows). Am Ende der Funktion wird von "Call hook for custom markers" gesprochen:
// Call hook for custom markers if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['comments']['comments_getComments'])) { foreach($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['comments']['comments_getComments'] as $userFunc) { $params = array( 'pObj' => &$this, 'template' => $template, 'markers' => $markerArray, 'row' => $row, ); if (is_array($tempMarkers = t3lib_div::callUserFunction($userFunc, $params, $this))) { $markerArray = $tempMarkers; } } }
Die Schleife erwartet nach dem Aufruf der Funktion callUserFunction ein Array, welches die aktualisierten Marker enthält. Als Übergabe Parameter werden $param und $this angegeben.
Programmlogik erstellen:
Nun wechselt man in das zuvor erstelle Extensionverzeichnis, im folgenden EXT:my_extension genannt, und erstellt zunächst einen Ordner "pi1". In diesem Order wird die Datei "class.tx_my_extension_pi1.php" erstellt.
So in etwa könnte der Inhalt der Datei "class.tx_my_extension_pi1.php" aussehen:
class tx_myextension_pi1 { function my_function($params, &$Obj) { $markerArray = $params['markers']; $markerArray['###UID###'] = $params['row']['uid']; return $markerArray; } }
Wie weiter oben schon beschrieben werden der Funktion zwei Parameter übergeben, $params und $this. Da in diesem Zusammenhang $this seine eigene Bedeutung hat, ändert man diese Variable auf einen beliebigen aussagekräftigen Wert, wie z.B. $Obj.
In diesen weniger Codezeilen wird dem $markerArray ein Marker ###UID### hinzugefügt der die UID des jeweiligen Kommentars beinhaltet.
Nachdem die Programmlogik nun steht muss der Hook nur noch eingebunden werden.
Hook einbinden:
In der zuvor erstellen "ext_localconf.php" wird folgender Code hinzugefügt:
if (!defined ('TYPO3_MODE')) die ('Access denied.'); $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['comments']['comments_getComments'][] = 'tx_myextension_pi1->my_function';
In der zuvor erstellen "ext_tables.php" wird folgender Code hinzugefügt:
require_once(t3lib_extMgm::extPath('my_extension') . 'pi1/class.tx_my_extension_pi1.php');
Anschießend muss noch der Cache geleert werden und der Marker ###UID### steht nun im Templateabschnitt zur Verfügung und kann eingebaut und verwendet werden.
Hook als getUserObj
Um die Verwendung eines Hooks über die Funktion getUserObj zu demonstrieren wird die Extension "tt_news" als Beispiel gewählt. In der Single-View Ansicht soll ein Textlink eingefügt werden der mit einem Anker am Ende der Seite verknüpft ist. Der Textlink soll die From <a href="###PAGE_URL####tx-comments-###NEWS_UID###"> bekommen. Somit muss der Markter ###PAGE_URL### neu erstellt werden. Der Marker ###NEWS_UID### steht in diesem Template-Abschnitt bereits zur Verfügung.
Hook Einbindung im Quelltext finden:
Wieder muss der entsprechende Code der Hook Verwendung im Quelltext der Extension gefunden werden. Hier für wechselt man zunächst in folgende Datei:
EXT:tt_news/pi/class.tx_ttnews.php
In Zeile 1552 befindet sich die Funktion function getItemMarkerArray($row, $lConf, $textRenderObj = 'displaySingle'). Am Ende der Funktion ist wieder von "Adds hook for processing of extra item markers" die Rede. Folgender Code ist hier bei von Bedeutung:
if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['extraItemMarkerHook'])) { foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['extraItemMarkerHook'] as $_classRef) { $_procObj = & t3lib_div::getUserObj($_classRef); $markerArray = $_procObj->extraItemMarkerProcessor($markerArray, $row, $lConf, $this); } }
Dabei wird über die Klassen-Instanz die Funktion "extraItemMarkerProcessor" mit den Parametern $markerArray, $row, $lConf und $this aufgerunfen. Als Rückgabewert der Funktion wird wieder das Marker-Array $markerArray erwartet.
Programmlogik erstellen:
So in etwa könnte der Inhalt der Datei "class.tx_my_extension_pi1.php" aussehen:
class tx_my_function_pi1 { function extraItemMarkerProcessor($markerArray, $row, $conf, &$pObj) { $page_url = $_SERVER['REQUEST_URI']; $page_url = parse_url($page_url, PHP_URL_PATH); $page_url = substr($page_url, 1); $markerArray['###PAGE_URL###'] = $page_url; return $markerArray; } }
Hier bei ist darauf zu achten, dass die Funktion exakt so definiert werden muss, wie sie auch später aufgerufen wird. Wie man sieht ist dies hier der Fall:
$_procObj->extraItemMarkerProcessor($markerArray, $row, $lConf, $this);
Die aufgerufene Funktion ist vom Namen und Aufbau her identisch mit der Funktion, die in der Datei "class.tx_my_extension_pi1.php" definiert worden ist.
Hook einbinden:
In die zuvor erstellt "ext_localconf.php" wird folgender Code hinzugefügt:
if (!defined ('TYPO3_MODE')) die ('Access denied.'); $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['extraItemMarkerHook'][] = 'EXT:my_extension/pi1/class.tx_my_extension_pi1.php:tx_my_extension_pi1';
Anschießend muss noch der Cache geleert werden und der Marker ###PAGE_URL### steht nun im Templateabschnitt zur Verfügung und kann eingebaut und verwendet werden.
Noch keine Kommentare vorhanden