Erstellen einer Webseite

1. Einleitung

Das vorliegende Tutorial soll aufbauend auf den Ausführungen in den Grundlagen zeigen, wie auf einfache Weise eine Webseite mit den Mitteln des Adventure PHP Frameworks erstellt werden kann. Um die Anleitung einfach zu gestalten wird von einem aufwändigen Design Abstand genommen.

2. Anforderungen

Die zu erstellende Webseite soll Platz für ein Key-Visual, einen Header-Bereich, ein Menü und einen Bereich für den Inhalt und einen Footer bieten. Im Content-Bereich soll dynamischer Inhalt abhängig von einem URL-Parameter angezeigt werden. Grafisch betrachtet soll die Seite dann folgendes Aussehen haben:

Meine erste Webseite mit dem Adventure PHP Framework

3. Installation und Konfiguration

An dieser Stelle geht der Autor davon aus, dass der Leser lediglich ein Code-Pack (Pakete mit dem Namen apf-codepack-*.[zip | tar.gz | tar.bz2]) auf der Download-Seite bezogen hat. Diese Pakete beinhalten den Quellcode des Frameworks, die Strukturen einer Webseite bzw. die Konfigurationen werden nicht mitgeliefert. Nun muss das Paket in einen beliebigen Ordner unterhalb des DocumentRoot des lokalen Webservers entpackt werden. Um eine einheitliche Sprechweise zu haben, soll dieser Ordner apps/ genannt werden. Aus Gründen der Übersichtlichkeit wird der Ordner apps/ in einen Ordner testwebsite/, der unter dem DocumentRoot des Webservers erstellt wurde verschoben werden. Als weitere Schritte müssen nun die Strukturen für die Webseite generiert und die nach Grundlagen notwenigen Konfigurationsdateien erstellt werden. Dazu ist folgende Vorgehensweise ratsam:


3.1. Ordner-Struktur der Webseite erstellen

Hierzu soll unter testwebsite/apps/ die Struktur
Code
sites/ testwebsite/ pres/ templates/ documentcontroller/

erstellt werden. Diese dient später zur strukturierten Aufnahme der Template- und Controller- Dateien der Webseite.

3.2. Bootstrap-Datei anlegen

Da das Framework für die Verwendung einer zentralen Bootstrap-Datei konzipiert wurde, über die alle Requests der Besucher abgehandelt werden, muss diese nun im Ordner testwebsite/ angelegt werden. Der Inhalt der Datei kann aus der aktuellen index.php der Dokumentationswebseite kopiert und wie folgt angepasst werden. Der Einfachheit wegen wird auf die Verwendung des FrontControllers verzichtet, da auch dies die Handhabung für den Einsteiger erleichtert.

PHP-Code
// Page-Controller einbinden (APF-Core-Library) include_once('./apps/core/pagecontroller/pagecontroller.php'); // Front-Controller einbinden import('core::frontcontroller', 'Frontcontroller'); // Front-Controller erzeugen und konfigurieren $fC = &Singleton::getInstance('Frontcontroller'); $fC->setContext('projectone'); // Request-Abarbeitung starten und Ergebnis zum Client senden echo $fC->start('sites::testwebsite::pres::templates', 'website');

In der Code-Darstellung sind bereits implizit weitere Vereinbarungen über die Struktur des Codes enthalten, die die weiteren Schritte beeinflussen.

3.3. Template-Dateien anlegen

Wie im Code-Ausschnitt der index.php bereits festgelegt wurde, soll das zentrale Template der Webseite unter dem Ordner testwebsite/apps/sites/testwebsite/pres/templates liegen und website.html heißen. In dieser Datei legen wir nun das unter Kapitel 2 beschriebene HTML-Gerüst an und sehen die einzelnen Bereichen darin vor. Die Datei hat damit - gekürzt dargestellt - folgenden Inhalt:
APF-Template
<html> <head> <title>TestWebSite</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <style type="text/css"> [..] </style> </head> <body> <center> <table width="800" border="0" cellpadding="0" cellspacing="0" class="table_layout"> <tr> <td class="table_keyvisual"> K e y <br /> V i s <br /> u a l </td> <td class="table_header"> Header </td> </tr> <tr> <td class="table_menu"> <br /> Startseite <br /> Impressum </td> <td class="table_content"> Content </td> </tr> </table> </center> </body> </html>

Damit kann nach Starten des Webservers (z.B. XAMPP, oder eine lokale Apache- oder IIS-Installation mit PHP 4 oder 5 als Modul) durch Aufruf der URL
Code
http://localhost/testwebsite/
die Test-Webseite bereits betrachtet werden.


4. Erstellen der dynamischen Bereiche

Damit die zentralen Bereiche wie Header, Menü und Inhalt nicht auf jeder Inhaltsseite gepflegt werden müssen, werden diese in eigene Templates ausgelagert und an den entsprechenden Stellen eingebunden. Dazu werden drei weitere Template-Dateien unter testwebsite/apps/sites/testwebsite/pres/templates angelegt:
  • header.html: Inhalte des Headers
  • menu.html: Inhalte des Menüs
  • content.html: Inhalte der Webseite
Die Template-Datei website.html wird wie folgt geändert/ergänzt:
Html-Code
<html> <head> <title>TestWebSite</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <style type="text/css"> [..] </style> </head> <body> <center> <table width="800" border="0" cellpadding="0" cellspacing="0" class="table_layout"> <tr> <td class="table_keyvisual"> K e y <br /> V i s <br /> u a l </td> <td class="table_header"> <core:importdesign namespace="sites::testwebsite::pres::templates" template="header" /> </td> </tr> <tr> <td class="table_menu"> <core:importdesign namespace="sites::testwebsite::pres::templates" template="menu" /> </td> <td class="table_content"> <core:importdesign namespace="sites::testwebsite::pres::templates" template="content" /> </td> </tr> </table> </center> </body> </html>

Die Beschreibung des <core:importdesign />-Tags findet sich auf der Seite Standard TagLibs. Die drei genannten Dateien haben dabei folgenden Inhalt:

header.html:
APF-Template
Header

menu.html:
APF-Template
<br /> Startseite <br /> Impressum

content.html:
APF-Template
Content
Damit sind die Vorkehrungen getroffen, zentrale Elemente und den Inhalte der Webseite unabhängig vom Design derselben pflegen zu können. Der Aufruf der URL
APF-Template
http://localhost/testwebsite/
sollte nun eine zu Kapitel 3.4. identische Ausgabe im Browser zeigen.


5. Ausgabe der Inhalte

Aufbauend auf der unter Kapitel 4 skizzierten Trennung der Webseite in einzelne Views, soll nun in einem weiteren Schritt aufgezeigt werden, wie es möglich ist, die Webseite mit dynamischen Inhalten zu bestücken. Dabei sollen die Inhalte abhängig vom URL-Parameter Page ausgegeben werden. Dazu muss zunächst das Menü angepasst werden, damit bei Klick auf die Menü-Punkte auch die gewünschte Seite angefragt wird. Das funktioniert nun wie folgt:

menu.html:
APF-Template
<br /> <a href="./?Seite=Startseite">Startseite</a> <br /> <a href="./?Seite=Impressum">Impressum</a>
Beim Klick auf die beiden Menüpunkte wird die Seite selbst (Datei index.php) aufgerufen und mit dem Parameter Page ausgestattet. Um nun abhängig der Request-Variable Page Inhalte im Inhaltsbereich anzeigen zu können bedarf es einer dynamischen Komponente. Hier stehen dem Entwickler zwei Möglichkeiten zur Verfügung, die das Framework out-of-the-box bietet.


5.1. Inhalte aus Text-Dateien

Eine sehr einfache Möglichkeit ist es, dynamische Inhalte aus Text-Dateien im Inhaltsbereich darzustellen. Zu diesem Zweck bietet das Framework die unter Standard-Taglibs, Kapitel 3.1, dokumentierte TagLib <doc:createobject />. Diese muss gemäß den oben festgelegten Anforderungen entsprechend konfiguriert werden. Die Bibliothek erwartet, dass die sprachabhängigen Inhaltsdateien unter dem Ordner ./frontend/content/ liegen, der parallel zur Bootstrap-Datei existieren muss. Vorrausgesetzt, die Inhalte sollen in deutscher Sprache angezeigt werden, ist es notwendig für die beiden Beispiele die Dateien
  • ./frontend/content/c_de_startseite.html
  • ./frontend/content/c_de_impressum.html

mit den gewünschten Inhalten anzulegen. Da der Content im Inhaltsbereich angezeigt werden soll muss die dafür verantwortliche Template-Datei content.html wie folgt abgeändert werden:

APF-Template
<core:addtaglib namespace="tools::html::taglib" class="CreateDocumentFromFileTag" prefix="doc" name="createobject" /> <doc:createobject requestparam="Seite" defaultvalue="Startseite" />
Die TagLib erwartet, dass die Dateinamen nur Kleinbuchstaben enthalten. Auf Windows-Maschinen ist dies zwar zunächst unerheblich, überträgt man die Applikation jedoch auf einen LINUX-Rechner, wird die angesprochene Datei nicht gefunden!

5.2. Inhalte aus einer Datenbank

Eine weitere Möglichkeit bietet die Variante, die Inhalte aus einer Datenbank zu lesen und in den Inhaltsbereich der Seite einzubetten. Hierzu kann der Entwickler Gebrauch von einem Document-Controller machen, der dazu gedacht ist, dynamischen Inhalt zu erzeugen.

Zunächst muss dazu eine Tabelle in der Datenbank freier Wahl erzeugt werden, die den Inhalt aufnimmt. Diese kann mit folgendem SQL-Statement erzeugt werden:

APF-Template
CREATE TABLE demopage_content ( PageID tinyint(5) NOT NULL auto_increment, PageURLName varchar(50) NOT NULL default '', PageTitle varchar(50) NOT NULL default '', PageContent text NOT NULL, PRIMARY KEY (PageID), UNIQUE KEY PageURLName (PageURLName), KEY PageTitle (PageTitle) ) ENGINE=MyISAM;

Ähnlich der unter 5.1. gezeigten Änderung muss nun die Datei content.html angepasst werden:

APF-Template
<@controller namespace="sites::testwebsite::pres::documentcontroller" class="ContentController" @>

Mit diesem XML-Tag wird dem Page-Controller bekannt gemacht, dass zur Verarbeitung des aktuellen Templates einen Controller im Sinne des MVC-Patterns zu verwenden ist. Hierzu setzen wir einen (Document-)Controller ein. Diese von BaseDocumentController abgeleitete PHP-Klasse ist dann dafür verantwortlich, dass der dynamische Inhalt geladen und an der gewünschten Stelle ausgegeben wird.

Da die Inhalte aus der Datenbank gelesen werden wird zur Konnektierung der Datenbank die Komponente ConnectionManager verwendet. Die Controller-Datei

Code
testwebsite/apps/sites/testwebsite/pres/documentcontroller/ContentController.php

soll mit folgendem Inhalt gefüllt werden:

PHP-Code
import('tools::request', 'RequestHandler'); class ContentController extends BaseDocumentController { public function transformContent(){ $cM = &$this->getServiceObject('core::database','ConnectionManager'); $SQL = &$cM->getConnection('content-database'); // URL-Parameter beziehen $page = RequestHandler::getValue('Seite','Startseite'); // Parameter gegen SQL-Injections absichern $page = $SQL->escapeValue($page); // Inhalt der Seite auslesen $select = 'SELECT PageContent FROM demopage_content WHERE PageURLName = \''.$page.'\' LIMIT 1'; $result = $SQL->executeTextStatement($select); $data = $SQL->fetchData($result); // Inhalt der Seite ausgeben $this->setContent($data['PageContent']); } }

Der Quelltext des Controllers sollte selbstredend sein. Im Groben beschrieben wird hier nichts anderes in PHP-Code abgebildet, wie in einem herkömmlichen Script auch stehen würde.

Um auf die Datenbank zugreifen zu können erwartet die MySQL-Komponente eine Konfigurationsdatei unter dem Pfad

Code
testwebsite/apps/config/core/database/projectone/DEFAULT_connections.ini

Der Dateiname setzt sich aus dem Pfad

Code
testwebsite/apps/config/core/database/{CONTEXT}/

und dem Namen

Code
{ENVIRONMENT}_connections.ini

zusammen. Dabei entspricht {CONTEXT} dem Context der aktuellen Applikation und projectone lautet. Details zur Konfiguration können dem Kapitel Konfiguration entnommen werden.

Der Inhalt der Konfiguration muss an die lokale Datenbank-Installation angepasst werden, genügt jedoch folgendem Schema:

APF-Konfiguration
[content-database] DB.Host = "" ; Servername oder IP-Adresse der Datenbank DB.User = "" ; Benutzer DB.Pass = "" ; Passwort DB.Name = "" ; Name der Datenbank DB.Type = "MySQLx" [DB.DebugMode = "true|false" DB.Charset = "utf8" DB.Collation = "utf8_general_ci"]

6. Fazit und Ausblick

Die vorliegende Webseite zeigt nun aus einer Textdatei oder Datenbank stammende dynamische Inhalten an. Ein Manko der Implementierung liegt noch darin, dass nicht abgefangen wird, ob ein Inhalt tatsächlich in der Datenbank existiert. Im Fall eines nicht vorhandenen Datenbank-Inhalts wird keine Fehlerseite ausgegeben, bei Verwendung der Datei-Variante ist dies bereits in der TagLib vorgesehen.

Darüber hinaus fehlt bei der in Kapitel 5.2 beschriebenen Vorgehensweise die Möglichkeit, eine Seite zu erstellen, zu pflegen und zu löschen. Diese Aufgabe kann im Moment lediglich mit einem Datenbank-Administrationstool wie PHPMyAdmin oder einem dafür erstelltes Tool erledigt werden.

Der Einfachheit wegen wurde in diesem Tutorial darauf verzichtet eine korrekte 3-Schicht-Implementierung aufzuzeigen, da dies den Schwierigkeitsgrad erheblich erhöht hätte. Fortgeschrittene Benutzer sollten jedoch die Datenbank-Kommunikation nicht direkt in einem Document-Controller vornehmen, sondern eine Business-Komponente eingeführen, die dem Controller ein "Inhalts-Domain-Objekt" liefert, das dieser dann anzeigt. Diese kümmert sich dann um die Bereitstellung einer Fehlerseite, sollte die vom Benutzer gewünschte Seite nicht existieren. Konsequenterweise greift die Business-Komponente auf eine Service-Komponente der Daten-Schicht zurück, die schließlich die Daten physikalisch aus der Datenbank bezieht. Innerhalb der Datenschicht kann dann Gebrauch vom ConectionManager gemacht werden um die relevanten Daten aus der MySQL-Datenbank zu laden. Weitere Anregungen bieten hier die Tutorials

7. Download der Quellcodes

Die in diesem Tutorial erstellten Dateien können unter tutorial_testwebsite.zip heruntergeladen werden. Nicht im Archiv enthalten sind die Quellcodes des Frameworks, da diese, wie bereits erwähnt, auf der Seite Downloads bezogen werden können.

Kommentare

Möchten Sie den Artikel eine Anmerkung hinzufügen, oder haben Sie ergänzende Hinweise? Dann können Sie diese hier einfügen. Die bereits verfassten Anmerkungen und Kommentare finden Sie in der untenstehenden Liste.
« 1   »
Einträge/Seite: | 5 | 10 | 15 | 20 |
1
Kevin Weiland 10.10.2014, 13:27:58
der Aufruf ( $cM = & $this->getServiceObject('APF\core\database\ConnectionManager'); ) im ContentController führt zumindest bei mir zu der folgenden Exception.



Error-ID:
161d83a4b46c89cd359adcc25372f436

Message:
Class name must be a valid object or a string

Number:
1

File:
D:\Programme\xampp\htdocs\APF\core\service\ServiceManager.php

Line:
94

Ich bin jetzt ein wenig ratlos, da ich es nach dem Tutorial aufgebaut habe.

2
Christian 24.02.2013, 14:20:19
Hallo Keno,

das Tutorial sollte mit einer Version >=1.5 auf jeden Fall funktionieren.

> Wie bekomme ich eine Datenbankverbindung? Die Ordnerstruktur des Demopacks weicht der vom Tutorial ab siehe hierzu auch tutorial_testwebsite.zip.
Das Demopack (Sandbox) ist eine fertige Implementierung einer Spiel- und Entwicklungs-Umgebung und ist mit diesem Tutorial zunächst nicht vergleichbar. Beide Strukturen sind anwendbar und zeigen dir, dass das APF dem Entwickler erlaubt unterschiedliche Strukturen zulässt du wirst hierbei nicht eingeschränkt.

> Was ist richtig? Demopack oder Tutorial?
Beide Strukturen sind richtig!

Viele Grüße,
Christian
3
Keno 02.02.2013, 22:38:21
Guten Abend,
auf welcher Version basiert das Tutorial?
Habe mir die Version apf-demopack-1.16-php5.zip heruntergeladen und versucht die Tutorials durch zu arbeiten, komme jedoch nicht so wirklich damit zurecht.
Beispiel:
Wie bekomme ich eine Datenbankverbindung? Die Ordnerstruktur des Demopacks weicht der vom Tutorial ab siehe hierzu auch tutorial_testwebsite.zip.

Was ist richtig? Demopack oder Tutorial?
MfG Keno
4
Christian 07.05.2011, 12:02:55
Hallo copta,

danke für den Hinweis, ist korrigiert.
5
copta 18.04.2011, 14:21:42
Nutzt man in diesem Beispiel dynamische Inhalte aus einer Datenbank, fehlt in der content_v1_controller.php noch der Import des RequestHandlers:
import('tools::request', 'RequestHandler');
6
Christian 20.02.2011, 22:20:53
Hallo Struppi,

das sieht nach einem fehlerhaften Aufruf des Templates in der Methode loadDesign() aus. Evtl. steht dort im zweiten Argument mehr als "website". Sofern ja, korrigiere das mal zu

$page->loadDesign("sites::testwebsite::pres::templates","website");

Falls das nicht hilft, melde dich bitte im Forum, dann können wir das im Detail analysieren.
7
Struppi 14.02.2011, 17:03:06
Uncaught exception!
Exception-ID: 2349d4521df80b87b9e95297d1b9cdc6
Type: IncludeException
Message: [Document::__loadContentFromFile()] Design "prestemplateswebsite" not existent in namespace "sites::testwebsite"!
Number: 256
File: D:xampphtdocs
oot_apfappscorepagecontrollerpagecontroller.php
Line: 1560
8
Christian 08.06.2009, 23:39:14
Hallo Marc,

richtig, im Pfad fehlt ein "database". Ich habe das nun nachgetragen.

Vielen Dank,
Christian
9
Marc Dannemann 31.05.2009, 11:24:42
In der APF-Version, die ich im Moment verwende (1.9) ist der Pfad für die MySQL-Konfiguration nicht mehr so, wie im Tutorial beschrieben. Statt "/config/core/sites/testwebsite/DEFAULT_connections.ini" muss dieser Pfad nun um die Komponente "Database" erweitert werden. Der vollständige Pfad lautet demnach "/config/core/database/sites/testwebsite/DEFAULT_connections.ini"

Mfg Marc