Eigene phpBB Erweiterungen erstellen

Beschreibung: Dieser Artikel behandelt die grundlegenden Themen der Erweiterungserstellung

Kategorie: Extensions

Link zu diesem Artikel: Alles auswählen

[url=https://www.phpbb.de/kb/viewarticle?a=19]Knowledge Base - Eigene phpBB Erweiterungen erstellen[/url]

Dieser Artikel behandelt die grundlegenden Themen der Erweiterungserstellung. Weiterführende Themen finden sich im Artikel Eigene phpBB Erweiterungen erstellen (Fortgeschrittene Themen)

In phpBB ist es ab Version 3.1 möglich, Erweiterungen zu installieren, die das Verhalten von phpBB ändern, ohne dass es nötig ist, den vorhandenen Quellcode von phpBB selbst zu verändern. Dies hat für den Administrator diverse Vorteile, beispielsweise vereinfacht es das phpBB Update, aber auch die Installation und das Update von Erweiterungen wird sehr viel einfacher, beide bestehen normalerweise nur noch im Ersetzen der alten Dateien durch neue. Verfügbare Erweiterungen decken schon eine ganze Menge an Wünschen ab, aber oft gibt es doch noch Kleinigkeiten, die man nicht über verfügbare Erweiterungen anpassen kann. Auch in phpBB 3.1 und neuer lässt sich nach wie vor der phpBB Quellcode ändern um diese Änderungen zu erzielen - mit dem Nachteil, dass Updates wieder erheblich komplizierter werden. In vielen Fällen könnte man allerdings auch sehr einfach eine kleine Erweiterung erstellen, die genau das gleiche bewirkt und alle Vorteile von Erweiterungen in der Erweiterungsdatenbank mit sich bringt.

Insbesondere reine Templateänderungen lassen sich häufig mit sehr wenig zusätzlichem Aufwand in einer Erweiterung unterbringen. Hierzu braucht man im Regelfall lediglich den zusätzlichen HTML Code in eine eigene Datei mit dem richtigen Namen an die richtige Stelle legen (ggf. auch mehrere Dateien, wenn z.B. vorhandener Quellcode von zwei HTML Teilen eingeschlossen werden soll) und eine zusätzliche Datei mit dem Namen composer.json erstellen.

Im Folgenden ist die Erstellung solch einer Mini-Erweiterung beschrieben - der Artikel eignet sich daher ideal für Einsteiger in die Entwicklung von Erweiterungen. Zunächst wird die grobe Funktionsweise von phpBB bei der Einbindung von Erweiterungen beschrieben, um einen groben Überblick über das Erweiterungsverzeichnis zu geben. Anschließend folgen ein paar Anwendungsbeispiele, mit deren Hilfe sich die meisten kleineren Änderungen umsetzen lassen sollten.

Einbindung von phpBB Erweiterungen in phpBB

phpBB 3.1 und höher verwenden ein bekanntes PHP Framework um grundlegende Funktionen bereit zu stellen: Symfony. Dieses Framework stellt diverse Funktionen bereit, mit denen auch die Einbindung von Erweiterungen realisiert wird. Die genaue Funktionsweise dieses Frameworks ist für die Einbindung von Erweiterungen nicht weiter wichtig, allerdings lassen sich bei fortgeschrittener Entwicklung einige zusätzliche Symfony Features auch in Erweiterungen einsetzen.

Für den Anfang wichtig ist zunächst, dass sehr viele Dinge bei der Einbindung einer Erweiterung automatisch ablaufen. phpBB sucht an speziellen Stellen nach Dateien und verwendet diese automatisch zur richtigen Zeit, sofern sie vorhanden sind. Seitens des Entwicklers ist hierfür nichts weiter zu tun, als die Datei mit dem richtigen Namen und richtigen Inhalt an die richtige Stelle zu legen, um alles weitere kümmert sich phpBB. Gerade das ist für viele Entwickler am Anfang verwirrend, die z.B. den sequentiellen Programmablauf in phpBB 3.0 gewöhnt sind. Hier musste PHP Code, der an einer bestimmten Stelle ausgeführt werden sollte auch an genau dieser Stelle in den Quellcode eingefügt werden. Mit phpBB 3.1 gilt das in der Form nicht mehr. Wenn man allerdings weiß, an welchen Stellen phpBB nach welchen Dateien sucht, kann man diese Dateien für den gleichen Zweck einsetzen.

Zunächst daher hier eine Liste von Stellen, an denen phpBB automatisch nach Dateien mit speziellen Namen sucht, inklusive kurzer Beschreibung der jeweiligen Dateien:
Wenn nicht anders angegeben, beziehen sich Orte immer auf den Hauptordner einer Erweiterung, also z.B. ext/gn36/hookup/, die Einbindung erfolgt außerdem normalerweise nur bei aktiver Erweiterung.
  • In allen Unter-Unterordnern des ext/ Verzeichnisses (also z.B. ext/unterordner/unterunterordner) wird beim Aufruf der ACP Seite, die die Erweiterungen auflistet nach einer composer.json gesucht. Diese enthält die Bezeichnung der Erweiterung und einige grundlegende Informationen über die Erweiterung (z.B. Autor, Version, ggf. Abhängigkeiten etc.). Damit eine Erweiterung installiert werden kann muss diese Datei vorhanden sein.
  • Im Ordner config/ wird nach der Datei services.yml und der Datei routing.yml gesucht
    • Die services.yml enthält alle von dir definierten php Klassen, die in der Erweiterung vorkommen und macht sie phpBB bekannt. Sie wird bei jeder Interaktion zwischen PHP Klassen der Erweiterung und phpBB gebraucht, also immer dann, wenn über Templateänderungen hinausgehende Funktionen benötigt werden.
    • Die routing.yml gibt phpBB bekannt, unter welchen URLs Teile der Erweiterung innerhalb von phpBB erreichbar sein sollen und welche PHP Klassen und welche deren Methoden bei der Verwendung dieser URLs aufgerufen werden sollen. Sie wird daher bei Erweiterungen mit eigenständigen Unterseiten benötigt.
  • Bei jeder Installation, Deaktivierung und Löschung der Erweiterung wird nach der optionalen Datei ext.php gesucht. Diese kann verwendet werden, um den Ablauf des Installationsprozesses zu verändern.
  • Bei der Installation und jeder Aktivierung oder Löschung von Erweiterungen wird im Ordner migrations/ nach beliebigen php Dateien gesucht. Diese können verwendet werden, um Datenbankänderungen bei der Installation der Erweiterung vorzunehmen.
  • Bei aktiver Erweiterung wird im Unterverzeichnis styles/[stylename]/template/event/ nach Styledateien mit speziellen Namen gesucht die automatisch verwendet werden. Immer, wenn in phpBB Templates ein Event mit dem gleichen Namen wie die Dateien ausgegeben werden soll werden diese Dateien eingebunden. Findet sich also beispielsweise ein <!-- EVENT viewtopic_show_my_ext --> im phpBB Template, dann kann mit einer Datei namens viewtopic_show_my_ext.hmtl an genau dieser Stelle HTML Code eingefügt werden.
  • Styledateien werden allgemein unter styles/[stylename]/template bzw. styles/[stylename]/theme erwartet, Sprachdateien entsprechend unter language/[iso]/, die automatisierten Tools suchen dort nach den Dateien, wenn entsprechende PHP Befehle verwendet werden.
  • In den Sprachdateiverzeichnissen language/[iso]/ wird nach php Dateien mit speziellen Namen gesucht (permission_xxx.php sowie info_(u|m|a)cp_xxx.php) die beim Aufruf einiger spezieller phpBB Seiten automatisch eingebunden werden (z.B. die permission_xxx.php Dateien wenn man im ACP die Rechte einstellt, die info_xxx Dateien, wenn man sich im ucp, mcp oder acp befindet (gedacht für Menüeinträge)).
Eine erste einfache Erweiterung lässt sich bereits erstellen, indem man lediglich einige dieser automatisch eingebundenen Dateien verwendet (siehe folgender Abschnitt). Alles was eine Erweiterung tut muss über die beiden Konfigurationsdateien im config/ Ordner konfiguriert werden, oder in einer der automatisch eingebundenen Dateien stattfinden.

Der Ablauf ist also gedanklich immer entweder
  • phpBB (-> routing.yml) -> services.yml -> deine Klasse mit eigenem Code oder
  • phpBB -> dein Code an einer speziellen Stelle.
Im folgenden werden einige Dateien angelegt. Diese liegen immer im Verzeichnis der Erweiterung, /ext/gn36/infobar/.
Außerhalb dieses Verzeichnisses müssen keine Dateien angelegt werden und Pfade beziehen sich, sofern sie nicht mit /ext/ beginnen, immer auf das Verzeichnis der Erweiterung!

Einfaches Beispiel mit ausschließlich Template Änderungen

Im folgenden wollen wir nun eine minimalistische Beispielerweiterung erstellen, die einen Informationsbalken über dem Hauptinhalt jeder Seite des Boards anzeigt. Hierzu benötigen wir lediglich zwei Dateien: Eine composer.json, die für jede Erweiterung benötigt wird und eine Template Datei mit dem HTML Code des Informationsbalkens. Es sind keinerlei PHP Kenntnisse für diese Erweiterung erforderlich.

Da beide Dateien an speziellen Stellen liegen müssen legen wir zunächst einen eigenen Ordner für unsere Erweiterung an: ext/gn36/infobar/. Hierbei solltest du gn36 und infobar durch deinen eigenen Namen ersetzen. Ersteres ist normalerweise ein Benutzername, zweiteres der Kurzname der Erweiterung. Verwende dabei keine Unterstriche und am besten auch sonst keine Sonderzeichen.

In diesen Ordner legen wir nun unsere composer.json:

Code: Alles auswählen

{
    "name" : "gn36/infobar",
    "type" : "phpbb-extension",
    "description" : "Mini-Erweiterung zu Demonstrationszwecken. Der Eintrag 'name' muss dem Ordnerpfad unterhalb von ext/ entsprechen. Du kannst alle Informationen in dieser Datei auf deine Bedürfnisse anpassen.",
    "version" : "1.0.0",
    "license" : "GPL-2.0",
    "require" : {
        "php" : ">=5.3.3"
    },
    "authors" : [{
        "name" : "Martin Beckmann",
        "email" : "mail@example.com",
        "homepage" : "https://www.phpbb.de/",
        "role" : "Lead developer"
    }],
    "extra" : {
        "display-name" : "Mini-Erweiterung - dieser Titel wird im ACP angezeigt",
        "soft-require" : {
            "phpbb/phpbb" : ">=3.1.5,<3.2@dev"
        }
    }
}
Achte bei der Eingabe auf korrekte Anführungszeichen und Kommas - nach jedem Wertepaar muss ein Komma folgen, sofern auf der selben Ebene noch weitere Daten in der Liste stehen. Hinter dem letzten Eintrag auf einer Ebene darf aber kein Komma stehen.
Wenn du die Datei angelegt hast solltest du die Erweiterung im ACP bereits sehen und aktivieren können. Wenn nicht hast du vermutlich einen Tippfehler gemacht und Klammern oder Kommas sind falsch oder fehlen.

Als nächstes wollen wir nun unseren Infobalken anlegen. Hierzu genügt es eine Datei mit dem Namen overall_header_content_before.html in den Ordner ext/gn36/infobar/styles/prosilver/template/event/ zu legen und folgenden HTML Code in die Datei einzufügen:

Code: Alles auswählen

<div class="rules">
    <div class="inner">
        <strong>Warnung:</strong> Dieses Board ist noch in der Entwicklung. Dabei können Fehler auftreten.
    </div>
</div>
 
Aktivierst du nun die Erweiterung (oder löscht den Cache sofern sie bereits aktiviert ist), dann sollte der Info Balken oberhalb des Seiteninhalts auf jeder Seite des Forums angezeigt werden. Auf ähnliche Weise lässt sich an vielen weiteren Stellen HTML Code in die Templates einfügen. Hierzu muss man sich lediglich im phpBB Template das richtige Event heraussuchen, bei dem man den Code einfügen möchte. Bennenst du beispielsweise die eben angelegte HTML Datei in overall_footer_content_after.html um, so wird der Balken unterhalb des Seiteninhalts auf jeder Boardseite angezeigt. Einen Link im Header neben dem FAQ Link kannst du beispielsweise in einer Datei namens overall_header_navigation_prepend.html anlegen.

Um das für dich passende Event zu finden kannst du in die Templates schauen, einfacher geht es aber mit der Erweiterung Show phpBB Events (for extension developers), die für alle verfügbaren Template Events eine kleine Box an der Stelle des Events ins Template einfügt, in der der Name des jeweiligen Events steht. Alternativ dazu findest du hier eine Liste mit sämtlichen Template-Events: phpBB Template Events.
Diesen Namen musst du nun für deine HTML Datei verwenden (mit der Datei-Erweiterung html) und in den gleichen Ordner legen wie die HTML Dateien in obigem Beispiel um an den entsprechenden Stellen HTML Code einzufügen. Achte darauf, dass dein HTML Code zu der Stelle passt, an der er eingefügt wird. Einige Events befinden sich beispielsweise innerhalb von Listenelementen wie <ul> oder <ol>. Hier solltest du dementsprechend deine Einträge mit <li> umschließen. Du kannst die HTML Dateien so behandeln als seien sie direkt an der entsprechenden Stelle im Template eingebaut. Alles was du in Template Dateien verwenden kannst darfst du auch hier verwenden.

Sofern du ein Template einsetzt, das nicht auf prosilver Basis läuft (also auch nicht von prosilver erbt) solltest du natürlich deine Templates in einen Unterordner mit entsprechendem Namen legen damit obiges Beispiel auch in deinem Forum funktioniert. Sofern deine Änderung mit beliebigen Templates funktioniert, ohne dass spezielle Anpassungen erforderlich sind kannst du auch statt prosilver den Ordner all verwenden. Dieser wird z.B. in der oben erwähnten Template Events Erweiterung verwendet.

Weitere hilfreiche Informationen zur Nutzung von Templates: KB:template_system

Eigenständige php Seiten in phpBB einbinden

Um eigenen PHP Code im Kontext von phpBB auszuführen ist schon etwas mehr Aufwand nötig. Als Grundstruktur brauchen wir wieder einen Ordner für die Erweiterung und eine composer.json (siehe oben).

Da unsere neue Seite über irgend eine URL erreichbar sein soll brauchen wir eine weitere automatisch eingebundene Datei: Die config/routing.yml. Diese ist dafür verantwortlich, URLs festzulegen, die in einer Erweiterung verwendet werden. phpBB liest die Datei automatisch ein und leitet Anfragen an die darin befindlichen URLs automatisch an die richtigen Stellen in der Erweiterung weiter.

Lege daher nun eine config/routing.yml Datei mit folgendem Inhalt an:

Code: Alles auswählen

# Mit # beginnen Kommentare
name_der_route_mit_beliebiger_laenge:
    # Nur mit leerzeichen einruecken, nie mit tabs
    # Der path enthaelt die gewuenschte URL vom Forum Root aus gesehen
    path: /gewuenschte/route/zur/datei/
    # In der naechsten Variable wird definiert was fuer ein Controller aufgerufen werden soll
    # In der Route können auch parameter enthalten sein. In dem Fall den parameternamen in eckigen klammern an der gewünschten Stelle angeben
    # z.B. /gewuenschte/route/zur/datei/{parameter_1}
    defaults: { _controller: "gn36.infobar.controller.routenhandler:methodenname", parameter_1: "standardwert" }
Achte darauf, dass du für die Einrückung nur Leerzeichen verwendest, Tabs sind in dieser Datei verboten. Die Einrückung ist wichtig.
In der Datei sind nun einige unbekannte Angaben.

Diese Datei sorgt nun dafür das eine URL in der Form /gewuenschte/route/zur/datei/ unterhalb des Forums automatisch an die Erweiterung weitergereicht wird. Damit klar ist, wo die Verarbeitung in der Erweiterung stattfinden soll ist ein Controller mit der Bezeichnung gn36.infobar.controller.routenhandler angegeben. Innerhalb dieser Klasse wird dann die Methode methodenname aufgerufen, deren Parameter parameter_1 mit dem Standardwert "standardwert" befüllt wird, wenn die Methode aufgerufen wird.

An dieser Stelle ist nun unklar, was genau die Klasse gn36.infobar.controller.routenhandler eigentlich genau ist. Auch phpBB kann mit der Bezeichnung normalerweise erst einmal nicht viel anfangen, deshalb schaut es an einer anderen Stelle nach: In der config/services.yml. In dieser Datei werden alle Klassen definiert, die in irgend einer Weise Arbeit für die Erweiterung verrichten. Für Klassen mit Sonderfunktionen müssen in dieser Datei spezielle Einträge angelegt werden, woraufhin phpBB diese Klassen dann gesondert berücksichtigt, beispielsweise für PHP Events, Benachrichtigungen oder Cronjobs. Für unsere Zwecke tut es an dieser Stelle ein ganz normaler Eintrag in der Datei, der einfach nur festlegt, welche Klasse denn nun mit der Bezeichnung gn36.infobar.controller.routenhandler gemeint ist:

Code: Alles auswählen

gn36.infobar.controller.routenhandler:
    # Hier muss sich der Pfad der Klassendatei wiederspiegeln
    # in diesem Fall liegt die Klasse also in einer Datei mit dem Namen routenhandler.php im Ordner ext\gn36\infobar\controller\
    class: gn36\infobar\controller\routenhandler
    # Parameter, die der Klasse im Konstruktor übergeben werden sollen. Wenn man z.B. das Template braucht kann man es hier anfordern
    # Hilfreich ist auch oft die Controller Helfer Klasse
    # Passend dazu braucht man aber auch eine Methode '__construct(\phpbb\template\template $template, \phpbb\controller\helper $helper) in der man das Template in eine globale Variable speichert.
    arguments:
        - '@template'
        - '@controller.helper'
Mit diesen Informationen weiß phpBB nun, dass die Klasse unter ext/gn36/infobar/controller/routenhandler.php zu finden ist. Sie benötigt für die Initialisierung das Template Objekt und den Controller Helfer als Parameter im Konstruktor. Aus der routing.yml ist ja bereits bekannt, dass die Methode methodenname aufgerufen werden soll, auch der notwendige Parameter ist bekannt. Somit kann phpBB nun bei Aufruf der URL die Klasse einbinden und die entsprechende Methode aufrufen, diese Methode sollte sich dann um die Darstellung unserer zusätzlichen Seite kümmern.

Dementsprechend brauchen wir nun eine neue Datei, die den PHP Code für unsere Klasse enthält. Diese muss dann unter ext/gn36/infobar/controller/routenhandler.php abgelegt werden und muss dann in etwa so aussehen:

Code: Alles auswählen

namespace gn36\infobar\controller;

class routenhandler
{
    // Das folgende dient u.a. dazu, in einem vernünftigen Editor das autocomplete Feature zu befüttern
    // Gleichzeitig wird mit dem protected die Variable vor dem Zugriff von außen beschützt
    /** @var \phpbb\template\template */
    protected $template;

    /** @var \phpbb\controller\helper */
    protected $helper;

    // Konstruktor - wird beim Erstellen des Objekts automatisch aufgerufen
    public function __construct(\phpbb\template\template $template, \phpbb\controller\helper $helper)
    {
       // Übergebene Templatevariable speichern
        $this->template = $template;
        $this->helper = $helper;
        // Wenn man noch weitere globale braucht, z.B. $user o.ä. dann sollten die auch passend übergeben werden (also hier und in der services.yml ergänzen)
    }

    // Der eigentliche Arbeitssklave
    public function methodenname($parameter_1)
    {
        //Hier kann man dann beliebige Dinge machen die z.B. zu einer Ausgabe führen
        // Templatevariable weiterverwenden
        $template = $this->template;
        //... Beliebiger Code ....
        $template->assign_vars(array(
            'CURRENT_TIME' => date('d.m.Y H:i:s'),
            'THE_PARAMETER' => $parameter_1,
        ));
        $seitentitel = 'Der Seitentitel am' . date('d.m.Y H:i:s');
        // Den Link auf die in der routing.yml definierte Route bekommt man z.B. mit Hilfe von $this->helper->route('name_der_route_in_der_routing_yml')
        return $this->helper->render('templatedateiname.html', $seitentitel);
    }
}
Wie man sieht tut die Methode noch nicht wirklich viel. Sie speichert die im Konstruktor übergebenen Variablen in geschützten Klassenvariablen. Dann fügt Sie in der über die URL ausgeführten Methode dem Template eine Variable mit dem aktuellen Zeitstempel hinzu und gibt den übergebenen Parameter in einer weiteren Templatevariable aus. Danach wird eine Variable für den Seitentitel mit dynamischem Inhalt befüllt. Anschließend wird die Helferklasse verwendet um eine Templatedatei mit dem namen "templatedateiname.html" und dem eben definierten Seitentitel mit Hilfe der Methode "render" an den Browser zu liefern.

Damit das Beispiel komplett ist brauchen wir also noch eine Templatedatei mit dem Namen templatedateiname.html. Diese Datei wird von phpBB automatisch gefunden, wenn sie entweder im phpBB Template Verzeichnis liegt, oder aber im Templateverzeichnis der Erweiterung. An erstere Stelle sollten wir sie nicht legen, denn dann sind nicht mehr alle Templatedateien an einem Ort. Daher legen wir die Datei unter ext/gn36/infobar/styles/prosilver/template/ mit folgendem Inhalt an:

Code: Alles auswählen

<!-- INCLUDE overall_header.html -->
<p>Das hier ist der Hauptinhalt der Datei. Zeitstempel: {CURRENT_TIME}</p>
<p>Parameter: {THE_PARAMETER}</p>
<!-- INCLUDE overall_footer.html -->
Nun ist das Beispiel komplett. phpBB kann anhand der routing.yml feststellen, dass wir beim Aufruf der URL /gewuenschte/route/zur/datei/ unterhalb des Forums die Methode methodenname der Klasse gn36.infobar.controller.routenhandler aufrufen möchten. Aus der services.yml kann phpBB entnehmen, dass diese Klasse unter ext/gn36/infobar/controller/ in der Datei routenhandler.php zu finden ist, den Namen routenhandler trägt und außerdem bei der Initialisierung das Templateobjekt sowie den Controller Helfer benötigt. Wenn die URL aufgerufen wird wird der Standardparameter "standardparameter" übergeben und der PHP Code der Methode wird ausgeführt. Dieser bindet schließlich die Templatedatei ein, nachdem er einige Templatevariablen mit Inhalt gefüllt hat.

Wenn wir nun die Erweiterung deaktivieren und wieder aktivieren können wir nun auf unsere neue Seite zugreifen. Wenn das Forum unter http://localhost/forum/ erreichbar ist finden wir unsere Seite unter http://localhost/forum/gewuenschte/route/zur/datei/. Sofern mod_rewrite nicht aktiv ist müssen wir noch ein app.php in den Pfad einfügen: http://localhost/forum/app.php/gewuenschte/route/zur/datei/.

Natürlich lässt sich in der von phpBB aufgerufenen Methode beliebiger php Code ausführen, diese ist somit ein Ersatz für die bisherigen in phpBB eingebundenen Seiten. Es ist auch nicht zwingend erforderlich, vom Templatesystem Gebrauch zu machen. In der Methode lassen sich auch übliche Ausgabebefehle wie echo oder print nutzen, ggf. muss man lediglich am Ende der Methode die Ausführung mit [php:exit] oder [php:die] beenden.

Sofern für die eigenen Zwecke noch weitere phpBB Objekte wie z.B. $user, $db oder $auth benötigt werden, so sollten diese ebenfalls über die services.yml und den Konstruktor angefordert und in Klassenvariablen gespeichert werden. Alle Klassen, die in irgend einer services.yml Datei aufgelistet werden können angefordert werden, also z.B. auch eigene zur Erweiterung gehörige Klassen. Eine Schwierigkeit hierbei sind die Namen, die in der services.yml verwendet werden müssen. Die zu phpBB gehörigen Klassen sind alle im Verzeichnis config/ definiert, die zugehörigen Klassen liegen unter phpbb/. Der in der services.yml zu verwendende Name einer Klasse ist immer die Überschrift des betreffenden Eintrags in der yml Datei. Für die Datenbank findet sich der Eintrag beispielsweise in der config/db.yml und heißt dbal.conn, die User Klasse findet sich in der user.yml und trägt die Bezeichnung user, die Auth Klasse ist in der auth.yml mit der Bezeichnung auth.

Klassen werden in der services.yml mit einem @ vor der Bezeichnung eingebunden, daneben gibt es auch noch Variablen, die von % Zeichen umgeben sind. Beide sollten in einfachen Anführungszeichen stehen wie im Beispiel angegeben. Die Parameter in der services.yml müssen in gleicher Reihenfolge gelistet werden, wie sie im Konstruktor benötigt werden. Klassen stehen unter der Überschrift services:, davor kann auch noch ein Bereich parameters: eingefügt werden, in dem Variablen definiert werden können wenn man z.B. den selben Wert für mehrere Klassen verwenden will. Auch einige Standardwerte wie z.B. der relative phpBB Pfad ($phpbb_root_path in phpBB 3.0) oder die php Dateierweiterung ($phpEx) kann als Variable übergeben werden (%core.root_path% bzw. %core.php_ext%). Am besten schaut man sich einfach ein paar Beispiele an - die yml Dateien in phpBB folgen der gleichen Syntax der auch die services.yml Datei in Erweiterungen folgen muss. Grundlage hierfür ist die Symfony dependency injection, diese lässt sich voll verwenden, ist allerdings nicht leicht zu verstehen.

Wenn wir möchten, können wir in der routing.yml auch weitere URLs angeben, die zum selben Ziel führen. Oder aber, wir können den Parameter, der aktuell fest eingestellt ist, als variablen Teil der URL definieren. So kann beispielsweise mit der Route /gewuenschte/route/zur/datei/{parameter_1} der Parameter dynamisch mit der Fortsetzung der URL gefüllt werden. Die Datei routing.yml könnte hierfür wie folgt ergänzt werden:

Code: Alles auswählen

name_der_zusaetzlichen_route:
    path: /gewuenschte/route/zur/datei/{parameter_1}
    defaults: { _controller: "gn36.infobar.controller.routenhandler:methodenname", parameter_1: "standardwert" }
Sofern beide URLs funktionieren sollen muss die bisherige Route zusätzlich enthalten sein - parameter_1 darf in der URL nicht leer sein.
Module im Persönlichen Bereich, Moderationsbereich und Adminbereich nehmen eine Sonderstellung ein. Ihre Verwendung ist gegenüber phpBB 3.0 kaum verändert, so dass die meisten hier vorgestellten Konzepte für diese leider nicht funktionieren.

Das Verhalten von phpBB verändern

In einigen Fällen möchte man das Verhalten von phpBB an einigen Stellen gezielt verändern. Vielleicht möchte man Themen mit einem besonderen Präfix nur Moderatoren anzeigen, Beiträge von bestimmten Benutzern besonders hervorheben oder einen Link im Header nur bestimmten Benutzergruppen anzeigen.

In den meisten Fällen kommt man in diesem Fall mit reinen Templateänderungen nicht mehr aus sondern benötigt zusätzlich Änderungen am Verhalten in den PHP Dateien. Auch diese möchten wir natürlich ohne Änderungen an den PHP Dateien von phpBB realisieren. Hierfür sind - ähnlich den Events im Template, mit denen Templatedateien eingebunden werden - auch in den PHP Dateien Events verteilt.

Trifft phpBB bei der Ausführung auf einen Event Trigger, so verpackt es einige nützliche Variablen in ein Event Objekt und ruft dann für alle Erweiterungen die Methoden auf, die dieses Event verarbeiten sollen. Das zuvor erstellte Event Objekt wird dabei allen Methoden der Reihe nach übergeben und kann von diesen verändert werden. Abschließend extrahiert phpBB die ggf. veränderten Variablen wieder aus dem Objekt und fährt mit der Ausführung des Skripts fort.

Um auf so ein Event zu reagieren genügt es allerdings dieses mal nicht, einer PHP Datei einen speziellen Namen zu verpassen und diese an einen vordefinierten Ort zu legen, sondern es sind zwei Dinge nötig:
  1. Ein spezieller Eintrag in der config/services.yml
  2. Eine PHP Klasse, die das Event verarbeitet und mindestens eine verarbeitende Methode sowie eine öffentliche, statische Methode mit dem Namen getSubscribedEvents besitzt.
Der Eintrag in der services.yml teilt phpBB mit, dass es eine Klasse gibt, die Events verarbeiten soll und wo diese liegt. Hier wird lediglich festgelegt, dass die Klasse überhaupt irgendwelche Events verarbeitet, nicht aber welche Events das sind. Die statische Methode getSubscribedEvents teilt phpBB dann mit, welche Events genau in der Klasse verarbeitet werden sollen.

Der Eintrag in der services.yml kann z.B. wie folgt aussehen:

Code: Alles auswählen

# Auch hier muss natürlich, wenn das der einzige Eintrag ist vorher die Überschrift services: angeführt werden
    gn36.infobar.events.global_events:
        class: gn36\infobar\event\global_events
        arguments:
            - '@user'
            - '@template'
            - '@config'
        tags:
            - { name: event.listener }
 
Der einzige Unterschied zum bereits bekannten Eintrag der services.yml sind die letzten beiden Zeilen. Hiermit wird die Klasse für phpBB speziell markiert (engl. "tag"). Der Tag mit dem Namen "event.listener" teilt phpBB hierbei mit, dass diese Klasse auf Events reagiert und deshalb bei der Verarbeitung von PHP Events berücksichtigt werden muss.

Die PHP Klasse muss nun entsprechend der Definition in der services.yml unter ext/gn36/infobar/event/ in einer Datei namens global_events.php liegen.

Sie kann z.B. wie folgt aussehen:

Code: Alles auswählen

<?php
namespace gn36\infobar\event;

class global_events implements \Symfony\Component\EventDispatcher\EventSubscriberInterface
{
        static public function getSubscribedEvents()
        {
                return array(
                        'core.user_setup'               => 'load_global_lang',
                        // Weitere Events
                );
        }

        /** @var \phpbb\user */
        protected $user;

        /** @var \phpbb\template\template */
        protected $template;

        /** @var \phpbb\config\config */
        protected $config;
        public function __construct(\phpbb\user $user, \phpbb\template\template $template, \phpbb\config\config $config)
        {
                $this->user = $user;
                $this->template = $template;
                $this->config = $config;
        }

        public function load_global_lang($event)
        {
                //Sprachdateien in beliebigen Dateien einbinden wenn sie gerade gebraucht werden
                //$this->user->add_lang_ext('gn36/infobar', 'global');
                // Sprachdateien global einbinden
                $lang_ary = $event['lang_set_ext'];
                $lang_ary[] = array(
                        'ext_name'      => 'gn36/infobar',
                        'lang_set'      => 'global', //Name der Datei im Unterverzeichnis ext/gn36/infobar/language/[iso]/    ohne Dateiendung
                );
                $event['lang_set_ext'] = $lang_ary;
        }
}
 
Wichtig ist hierbei die Implementierung des "eventSubscriberInterface", die die Methode getSubscribedEvents fordert. Diese Methode gibt lediglich ein Array zurück, welches die verarbeiteten Events als Schlüssel und die verarbeitenden Methoden als Wert des Arrayeintrags enthält.

In der entsprechenden Methode erfolgt dann die eigentliche Verarbeitung. In diesem Beispiel wird auf das Event core.user_setup reagiert, welches beim Laden des Benutzerobjekts getriggert wird. Es ist speziell dafür gedacht, globale Sprachdateien zu laden, die z.B. für Menüeinträge oder ähnliches gebraucht werden, was auf allen Seiten zu finden ist. Hierfür wird das Array lang_set_ext aus dem Event geladen, um einen Eintrag erweitert und anschließend wieder in das Event zurückgeschrieben. Dies sorgt dafür, dass phpBB die Sprachdatei mit dem Namen "global.php" in der jeweils gültigen Sprache läd.

Eine Besonderheit fällt beim Blick auf den Umgang mit $event auf. Auf den ersten Blick ist man versucht, die Konstruktion mit der lokalen Variable zu ersetzen durch eine einfache Zuweisung:

Code: Alles auswählen

//falsch:
$event['lang_set_ext'][] = array(
    'ext_name'      => 'gn36/infobar',
    'lang_set'      => 'global', //Name der Datei im Unterverzeichnis ext/gn36/infobar/languages/[iso]/
); 
Das funktioniert aber in der Form nicht, weil $event kein Array, sondern ein Objekt ist und der direkte Schreibzugriff nur auf komplette interne Variablen des Objekts möglich ist, nicht aber auf Teile eines Arrays. Man kann also das komplette Array ersetzen, aber nicht lediglich einzelne Teile verändern.

Um das Beispiel abzuschließen brauchen wir nun noch eine Sprachdatei, die eingebunden wird und außerdem eine Templatedatei, in der eine Sprachvariable aus der Datei verwendet wird. Die Sprachdatei sollte dabei für alle Sprachen angelegt werden, die verfügbar sein sollen.

Für ein deutschsprachiges Forum legen wir also nun die Datei ext/gn36/infobar/language/de/global.php mit folgendem Inhalt an:

Code: Alles auswählen

<?php
if (!defined('IN_PHPBB'))
{
        exit;
}

if (empty($lang) || !is_array($lang))
{
        $lang = array();
}

$lang = array_merge($lang, array(
        // Notifications
        'SAMPLE_LANGVAR'                              => 'Generische Sprachvariable. Irgend einen Text eingeben',
));
Da phpBB auch immer eine englische Sprachdatei benötigt, kopieren wir die o.g Datei in das englische Sprachen Verzeichnis: ext/gn36/infobar/language/en/global.php
und passen die Übersetzung an:

Code: Alles auswählen

<?php
if (!defined('IN_PHPBB'))
{
        exit;
}

if (empty($lang) || !is_array($lang))
{
        $lang = array();
}

$lang = array_merge($lang, array(
        // Notifications
        'SAMPLE_LANGVAR'                              => 'Generic language variable. Enter any text',
));
Die Templatedatei overall_header_content_before.html die wir bereits zuvor angelegt haben könnte so aussehen:

Code: Alles auswählen

<div class="rules">
    <div class="inner">
        <strong>Warnung:</strong> {L_SAMPLE_LANGVAR}
    </div>
</div>
Wird die Erweiterung nun aktiviert sollte der Infobalken oben den Inhalt aus der Sprachdatei für die Sprachvariable einsetzen.

Natürlich ist das für das typische Forum ein nur begrenzt nützliches Beispiel, aber es verdeutlicht den Umgang mit dem Event Objekt. Das Eventobjekt enthält unterschiedliche Variablen abhängig davon, welches Event getriggert wird. Welche Variablen übergeben werden lässt sich aus der jeweiligen Beschreibung des verwendeten Events entnehmen. In vielen Fällen reichen bei geschickter Auswahl des verarbeiteten Events die übergebenen Variablen für kleinere Änderungen bereits aus, so dass man in der Erweiterung ohne komplexe Datenbankabfragen o.ä. auskommt.

Wer mehr über das Event Objekt wissen möchte (z.B. kann man mit dessen Hilfe auch die weitere Eventverarbeitung abbrechen und so verhindern, dass weitere Erweiterungen ausgeführt werden) sollte einen Blick in die Symfony Doku zum Thema werfen.

Ist man auf der Suche nach dem passenden Event für seine Zwecke, kann man einfach nach @event suchen. Eine andere nützliche Quelle für Events, falls man nicht weiß, in welcher Datei man schauen sollte ist die Event-Liste - phpBB Dev Docu.