WCF2: Zugriff auf die Datenbank

  • WCF 2

Warning: This page is a part of an archive now and will be removed in the future.

Nachdem durch die bisherigen Tutorials gezeigt wurde, wie man
  1. die erste eigene Erweiterung (Plugin) anlegt und damit die Example-Page hinzufügt,
  2. einen Menüpunkt hinzufügt,
  3. Inhalte über Nutzung eines Templatelistener hinzufügt,
  4. ACP-Einstellungen hinzufügt,
  5. benutzerbezogene Einstellungen anlegt,
  6. Inhalte über die Nutzung von Gruppenberechtigungen in der Sichtbarkeit steuern kann,
  7. LESS-Dateien (= CSS-Deklarationen) hinzufügt,
  8. Tooltips ins Template bekommt,
  9. das Paket updatefähig macht
wird nun auf die Benutzung der Datenbank angegangen.

Ziel dieses Tutorials ist es, dass man über die Benutzung der vorhandenen WCF-Klasse(n) und deren Methoden die E-Mail-Adresse eines bestimmten Benutzerkontos im Template des ersten eigenen Plugins angezeigt wird.

Eine der wichtigsten Neuerung im Vergleich zum WCF 1.x ist es, dass WoltLab mit Community Framework 2 die PHP-Erweiterung „Data Objects“ (PDO) benutzt. Diese Erweiterung ist kurz gesagt eine Schnittstelle, die einen konsistenten Zugriff auf Datenbanken verschiedener Hersteller bietet. Somit ist es vollkommen egal, welcher Typ von Datenbank eingesetzt wird. Solange ein PDO-Treiber für die Datenbank existiert, hat man immer die gleichen Möglichkeiten (Methoden), auf die Datenbank zuzugreifen.

WoltLab selbst liefert mit Community Framework 2 ebenfalls noch eine eigene Implementierung für den PDO-basierten Zugriff, was wiederum bedeutet, dass alle Zugriffe auf die Datenbank über die Methode getDB() der WCF-Klasse geschehen. Die angesprochene Methode liefert wie auch schon im WCF 1.x die „Verbindung zur Datenbank“.

Weiterhin gibt es eine Hand von (abstrakten) Klassen, die von jeder Anwendung/Erweiterungen implementiert werden sollten, falls sie Datenbanktabellen mitliefern. Durch die Implementierung der Klassen
  • AbstractDatabaseObjectAction
  • DatabaseObject
  • DatabaseObjectEditor
  • DatabaseObjectList
bekommt man objektbasierten Zugriff auf die Datensätze in den Tabellen.

Welche Aufgaben die Klassen haben, ist im englischsprachigen Wiki des WoltLab Community Framework 2 auf GitHub erklärt.

Um es mal am Beispiel von Burning Board 4 klarzumachen:
Burning Board 4 ist, wie der Vorgänger, auch eine Forensoftware, in der es hauptsächlich um die Erstellung bzw. Bearbeitung von Themen (Thread) und Beiträgen (Post) geht. Marcel Werk und Alexander Ebert haben für den objektbasierten Zugriff jeweils die oben genannten abstrakten Klassen abgeleitet und für den Zugriff auf die Beiträge eine wbb\data\post\Post, wbb\data\post\PostAction, wbb\data\post\PostEditor und wbb\data\post\PostList Klassendatei erstellt. Für den Zugriff auf die Themen wurden nach dem gleichen Schema die Klassen wbb\data\thread\Thread, wbb\data\thread\ThreadAction, wbb\data\thread\ThreadEditor und wbb\data\thread\ThreadList erstellt.

Benutzerobjekt aus der Datenbank auslesen

Als kleine Einführung wird nun gezeigt, wie ich einen bestimmten Datensatz aus der Tabelle wcfX_user (wobei X für die Installationsnummer von Community Framework steht) mit Hilfe einer Implementierung (wcf\data\user\User) vom DatabaseObject erhalte.

Wie man als Entwickler sicherlich weiß, hat jeder Benutzer die sogenannte Benutzer-ID (Attribut userID in der Datenbanktabelle). Diese userID identifiziert einen Benutzer eindeutig und ist mit vielen Tabellen verknüpft, da dadurch zum Beispiel die Beiträge im Forum den angemeldeten Benutzern zugeordnet werden.

Gehen wir nun davon aus, dass ich (Fighter456) mit der Benutzer-ID „456“ in der Datenbank eingetragen bin, und ich durch diese Information meine E-Mail-Adresse ermitteln will, um diese wiederum auf der "ExamplePage" auszugeben.
WoltLab hat nun unter dem Pfad wcf\data\user und mit der Klasse User die vorhandene DatabaseObject-Klasse abgeleitet/erweitert und bietet somit objektbasierten Zugriff auf die Datensätze der Tabelle wcfX_user (wobei X für die Installationsnummer von Community Framework steht).

Nun geht es darum, dass wir in der Klassendatei der ExamplePage meinen Datensatz als Objekt laden, die E-Mail-Adresse „ermitteln“ und ans Template zur Ausgabe übergeben.
Dazu wird die Klassendatei mit dem Editor/der IDE (in meinem Fall der NetBeans IDE) geöffnet und unter der Deklaration der öffentlichen Klassenvariable $activeMenuItem eine weitere Variable deklariert, die standardmäßig den „Inhalt“ null hat. In meinem Fall nenne ich sie jetzt einfach $myUserObject und füge darüber konsistenterweise einen Kommentar ein, der den Inhalt der Variable kurz beschreibt, von welchem Typ der Inhalt ist.

PHP Source Code: 20

  1. /**
  2. * Fighter456 user object
  3. * @var wcf\data\user\User
  4. */
  5. public $myUserObject = null;
Da wir eine Instanz der Klasse User erzeugen wollen, muss diese zur Laufzeit des Skriptes auch verfügbar sein. Im WCF 2 geschieht die Einbindung von Klassen mit Hilfe der use-Statements, die unter der namespace-Angabe in alphabetischer Reihenfolge eingefügt werden.
Dazu einfach use wcf\data\user\User; schreiben und schon kann die Klasse innerhalb der eigenen Klasse genutzt werden.
Auf die gleiche Art und Weise wird auch die WCF-Klasse zur Verwendung in der eigenen Klasse eingebunden. Der Pfad zu dieser Klasse kann problemlos über das Dateisystem ermittelt werden bzw. sollte bei korrekt eingerichteter Autovervollständigung von der IDE automatisch ergänzt werden, wenn man WCF eintippt und ENTER drückt.

Der Anfang der Klassendatei sollte nun wie folgt aussehen:

PHP Source Code: 1

  1. <?php
  2. namespace wcf\page;
  3. use wcf\data\user\User;
  4. use wcf\system\WCF;


Wie auch schon unter dem WCF 1.x gibt es für das Auslesen von Daten und der Übergabe von Informationen an das Templatesystem innerhalb von Page-Klassen vorgegebene Methoden. Die Namen dieser Methoden können samt Beschreibung in der Interface-Klasse IPage unter wcf\page nachgesehen werden. In der eigenen ExamplePage-Klasse werden diese Methoden durch die wcf\page\AbstractPage implementiert und müssen daher nun mitsamt eines parent::NAME_DER_METHODE()-Aufrufs überschrieben werden. Der parent-Aufruf sorgt dafür, dass die Implementierung in der AbstractPage ausgeführt wird, was aus dem Grund wichtig ist, da dort die registrierten EventListener angestoßen werden.

Wir benötigen für unser Vorhaben die Methoden readData() und assignVariables(), die wir nun überschreiben. Fangen wir an mit der readData(), in der wir eine Instanz der User-Klasse mit dem Datensatz des Benutzers mit der Benutzer-ID "456" erzeugen.

PHP Source Code: 26

  1. /**
  2. * @see wcf\page\IPage::readData()
  3. */
  4. public function readData() {
  5. parent::readData();
  6. $this->myUserObject = new User(456);
  7. }
Der Code hinter dem =-Zeichen führt aufgrund der Implementierung innerhalb der wcf\data\DatabaseObject::__construct() eine SELECT * FROM wcfX_user WHERE userID = 456-Abfrage durch und hält das Ergebnis der Abfrage in der Klasse gespeichert, so dass auf die Eigenschaften (= Attribute) der „user“-Datenbanktabelle zugegriffen werden kann, ohne dass Abfragen wie SELECT email FROM wcfX_user WHERE userID = 456 abgefeuert werden müssen. Auf Grund der weitergehenden Implementierungen ist beispielsweise der Zugriff auf den Benutzernamen nicht nur über $this->myUserObject->username, sondern auch über $this->myUserObject->getTitle() bzw. $this->myUserObject (über die magische „__toString()“-Methode) möglich.

E-Mail-Adresse ans Template übergeben und ausgeben

Nun geht es daran, dass wir die E-Mail-Adresse an das Templatesystem übergeben. Dazu wird die assignVariables()-Methode überschrieben. Der unten dargestellte Code übergibt ausschließlich die E-Mail-Adresse an die Templatevariable $email.

PHP Source Code: 35

  1. /**
  2. * @see wcf\page\IPage::assignVariables()
  3. */
  4. public function assignVariables() {
  5. parent::assignVariables();
  6. WCF::getTPL()->assign('email', $this->myUserObject->email);
  7. }
Abschließend ist es nur noch notwendig, die E-Mail-Adresse im Template auszugeben. Dazu wird die Templatedatei example.tpl ebenfalls zur Bearbeitung geöffnet und an der gewünschten Stelle die Templatevariable wie folgt ausgegeben:

Smarty-Template

  1. {@$email}


Wer möchte, kann davor auch eine Sprachvariable ausgeben, sodass bei Ausgabe "E-Mail-Adresse: HIER_STEHT_DIE_ADRESSE" erscheint. Der Code dazu würde folgendermaßen aussehen:

Smarty-Template

  1. {lang}wcf.user.email{/lang}: {@$email}

Der komplette Quellcode sollte nach der Implementierung etwa wie dieser aussehen:

PHP Source Code

  1. <?php
  2. namespace wcf\page;
  3. use wcf\data\user\User;
  4. use wcf\system\WCF;
  5. /**
  6. * Shows the example page.
  7. *
  8. * @author KittBlog Stile
  9. * @copyright 2013 kittblog.com
  10. * @license LGPL
  11. * @package com.kittblog.wcf.examplepage
  12. */
  13. class ExamplePage extends AbstractPage {
  14. /**
  15. * @see wcf\page\AbstractPage::$activeMenuItem
  16. */
  17. public $activeMenuItem = 'wcf.page.example';
  18. /**
  19. * user object from Fighter456
  20. * @var wcf\data\user\User
  21. */
  22. public $myUserObject = null;
  23. /**
  24. * @see wcf\page\IPage::readData()
  25. */
  26. public function readData() {
  27. parent::readData();
  28. $this->myUserObject = new User(456);
  29. }
  30. /**
  31. * @see wcf\page\IPage::assignVariables()
  32. */
  33. public function assignVariables() {
  34. parent::assignVariables();
  35. WCF::getTPL()->assign('email', $this->myUserObject->email);
  36. }
  37. }
Display All

Smarty-Template

  1. {include file='documentHeader'}
  2. <head>
  3. <title>{lang}wcf.page.example.title{/lang} - {PAGE_TITLE|language}</title>
  4. {include file='headInclude' sandbox=false}
  5. </head>
  6. <body id="tpl{$templateName|ucfirst}">
  7. {include file='header'}
  8. <header class="boxHeadline">
  9. <h1>{lang}wcf.page.example.title{/lang}</h1>
  10. </header>
  11. {include file='userNotice'}
  12. <div class="container marginTop">
  13. <ul class="containerList exampleList">
  14. <li class="exampleBox">
  15. <div>
  16. <div class="containerHeadline">
  17. <h3>{lang}wcf.page.example.secondTitle{/lang}</h3>
  18. <p>{lang}wcf.page.example.content{/lang}</p>
  19. {if EXAMPLE_PAGE_OPTION == true}
  20. {lang}wcf.page.example.optionTrue{/lang}
  21. {else}
  22. {lang}wcf.page.example.optionFalse{/lang}
  23. {/if}
  24. {if $__wcf->getUser()->getUserOption('examplePageNumber') == 10}
  25. {lang}wcf.page.example.userOption10{/lang}
  26. {elseif $__wcf->getUser()->getUserOption('examplePageNumber') == 20}
  27. {lang}wcf.page.example.userOption20{/lang}
  28. {else}
  29. {lang}wcf.page.example.userOption30{/lang}
  30. {/if}
  31. {if $__wcf->getSession()->getPermission('user.examplePage.canViewInfo')}<p>{lang}wcf.page.example.info{/lang}</p>{/if}
  32. {lang}wcf.user.email{/lang}: {@$email}
  33. {event name='example'}
  34. </div>
  35. </div>
  36. </li>
  37. </ul>
  38. </div>
  39. {include file='footer'}
  40. </body>
  41. </html>
Display All
Im nächsten Tutorial wird erklärt, wie man diese Information durch eine direkte SQL-Abfrage erhält. Weiterhin wird gezeigt, wie man diese Information dynamisch von einer bestimmten userID abfragen kann, wenn die Benutzer-ID in der URL angehängt ist.

Teil 9: Ein updatefähiges Paket erstellen
About the Author
Unspecified

3,185 times read

Comments 5

  • Der dem wo Hamburg wohnt -

    Wo ist denn nun das nächste Tutorial zu finden? :( Der Teil 11 ist nicht das, was angekündigt wurde, und ich finde den nächsten Teil nicht :(

  • Der dem wo Hamburg wohnt -

    Wo ist denn nun das nächste Tutorial zu finden? :( Der Teil 11 ist nicht das, was angekündigt wurde, und ich finde den nächsten Teil nicht :(

  • dartgott -

    Schönes Tutorial und sehr verständlich.
    Hat mir geholfen.
    Freue mich auf die nächsten für die Datenbankabfrage.
    Hoffe es gibt bald wieder etwas :D
    Danke

  • WbbFan -

    Ein wirklich hilfreiches Tutorial! Macht bitte weiter so!
    Bin schon gespannt auf das nächste! Die Ankündigung klingt schon vielversprechend!
    Bis hierhin schonmal vielen Dank!

  • CIA JOE -

    Toll das ihr euch so viel Mühe mit den Tutorials gebt. :thumbup: Da bekommt man gleich Lust was zu machen... Nur mit der Zeit sieht's nicht so toll aus. :|

    Jedenfalls wird auch dieses Tutorial vielen helfen.

This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.