>> Inhaltsverzeichnis

Allgemeines

Vorwort

Lieber Leser

Herzlich Willkommen und vielen Dank, dass Sie sich für Yana entschieden haben.

In diesem Programm stecken mehrere Jahre mühevoller Entwicklungsarbeit, sowie viele Stunden, welche unzählige helfende Hände investiert haben, um durch Tipps, Vorschläge und Programmtests dieses Programm stetig zu verbessern.

Alle diese Stunden haben mir und allen, die an diesem Projekt beteiligt waren, sehr viel Freude bereitet.

Wir hoffen, dass Ihnen das Ergebnis unserer Arbeit gefällt. Bitte berichten Sie uns von Ihren Erfahrungen. Falls Sie Vorschläge haben stehe ich Ihnen gern via E-Mail zur Verfügung.

Thomas Meyer

Beschreibung

Yana ist ein unternehmenstaugliches Framework für PHP mit dem Ziel, Ihren gesamten Entwicklungsprozess zu unterstützten - statt nur MVC zu liefern.

Diese Software ist eine Entwicklungsplattform für Webanwendungen in PHP, AJAX und SQL.
Sie bietet Rapid-Prototyping für einen einfachen, schnellen Start. Entwickler können auf einem simulierten Datenbankserver arbeiten, der automatisch die Datenbank aktualisiert, während sie arbeiten. Um live zu gehen, ist ein Deployment der Datenbank auf einem echten DBS jederzeit möglich. Ihre Webformulare und PHP-Code passen sich automatisch an Datenbankänderungen an. Die Software unterstützt mehrere DBMS - nicht nur MySQL. Sie bietet eine erweiterte Smarty Template-Engine mit Unterstützung für Skins. Professionelle Übersetzter erhalten Unterstützung durch automatisch erzeugte Sprachdateien nach OASIS XLIFF Standard. Entwickler finden eine flexible Pluginarchitektur, um hochgradig variable Softwareprodukte mit vielen Produktvarianten zu erstellen. Die Wartung unterstützen wir durch eingebaute Selbstdiagnose und eine hohe Testabdeckung. Ein grafische Installer ist in Vorbereitung, um Sie in der Deploymentphase durch den Installationsprozess zu führen.

Yana ist leicht zu erlernen und gut dokumentiert. Videotutorials and ein umfassendes Handbuch mit zahlreichen Abbildungen und Screenshots unterstützen Sie auf Ihren ersten Schritten.

Systemvoraussetzungen

Damit dieses Programm korrekt arbeitet, müssen folgende Mindestanforderungen erfüllt sein:

Folgende Konfiguration wird empfohlen:

Kompatibilitätshinweise

In diesem Abschnitt finden Sie Hinweise auf Eigenheiten bestimmter Systemkonfigurationen, sowie Informationen zu typischen Konfigurationsfehlern und Ratschläge, die Ihnen helfen können, falls während der Installation Probleme auftreten.

mitgelieferte Dateien

Falls Sie Skins, Plugins oder Übersetzungen erstellt haben und diese mit anderen teilen wollen, melden Sie sich. Gern stellen wir interessante Lösungen kostenlos zur Verfügung.
mitgelieferte Dateien (siehe Legende)
Dateien
1 index.php Startseite
2 library.php lädt Systembibliotheken
3 cli.php Kommandozeilenprogramm für Cron-Jobs
allgemeine Verzeichnisse
4 cache/ Verzeichnis für temporäre Dateien und Log-Files
5 common_files/smilies/ hier können neue Emoticons eingefügt werden
6 config/ Konfigurationsdateien
7 includes/ Yana Kernsystem
8 languages/ Übersetzer können hier neue Sprachdateien hinzufügen
9 libs/ weitere Bibliotheken
10 plugins/ PHP-Programmierer können hier eigene Erweiterungen der Anwendung speichern
11 skins/ Webdesigner können hier zusätzliche Skins und Layouts für die Anwendung speichern
Konfigurationsdateien
12 config/db/ Datenbanken und Konfigurationsdateien
13 config/profiles/ Einstellungen des Administrationsmenüs
14 config/dbconfig.php Parameter der Datenbankverbindung
16 config/system.config.xml Systemkonfiguration
16 config/system.drive.xml Pfadangaben zu Systemdateien
 

Copyright und Rechtliches

Lizenzen

Hinweis zu Lizenzen:
Das Installationspaket enthält Komponenten unterschiedlicher Hersteller.

"Yana Framework für PHP" von Thomas Meyer
Diese Software steht unter der GNU GPL. Deren Lizenzbedingungen können Sie hier ( gpl.txt ) einsehen.

"Handbuch zum Yana Framework" von Thomas Meyer
Dieses Handbuch steht unter der Creative Commons Attribution-Licence 3.0. Deren Lizenzbedingungen können Sie hier ( creativecommons.org/licenses/by/3.0 ) einsehen.

"Smarty Template-Engine" von New Digital Group
Diese Software steht unter der GNU LGPL. Deren Lizenzbedingungen können Sie hier ( lgpl.txt ) einsehen.

"PhpConcept Library - Zip Module" von Vincent Blavet
Diese Software steht unter der GNU LGPL. Deren Lizenzbedingungen können Sie hier ( lgpl.txt ) einsehen.

"The DHTML Calendar" von Mihai Bazon
Diese Software steht unter der GNU LGPL. Deren Lizenzbedingungen können Sie hier ( lgpl.txt ) einsehen.

"Tiny MCE"
Diese Software steht unter der GNU LGPL. Deren Lizenzbedingungen können Sie hier ( lgpl.txt ) einsehen.

"SQL-Parser" von Brent Cook
Diese Software steht unter der GNU LGPL. Deren Lizenzbedingungen können Sie hier ( lgpl.txt ) einsehen.

"JQuery" von John Resig
Diese Software steht unter der MIT-Lizenz. Deren Lizenzbedingungen können Sie hier ( mit.txt ) einsehen.

"Interactive Photo Desk" von Mary Lou
Diese Software steht unter der MIT-Lizenz. Deren Lizenzbedingungen können Sie hier ( mit.txt ) einsehen.

Zusammenfassung

Eine deutsche Übersetzung der GNU GPL v3 (rechtlich verbindlich ist nur die englische Originalfassung)

Als Gerichtsstand gilt der Wohnort des Autors.

Sie benutzen diese Software und die beiliegende Dokumentation auf eigene Gefahr. Für jegliche Schäden, welche in Folge der Benutzung dieser Software entstehen könnten übernimmt der Autor keinerlei Haftung.

An diesem Projekt teilnehmen

Sie sind herzlich eingeladen, Übersetzungen, Skins oder Quellcode beizutragen. Schreiben Sie einfach eine Mail. Für Fragen steht Ihnen das Forum jederzeit offen.

Sollten Sie nicht die Möglichkeit haben sich direkt zu beteiligen, sind Spenden stets gern gesehen.

Ansprechpartner:Thomas Meyer
Projektwebsite:www.yanaframework.net
Mail für Fragen:

Installationsanleitung

Variante 1: Installationsassistenten benutzen

Hinweis an PHP-Neulinge: Dieses Skript muss auf einem Server mit PHP-Unterstützung installiert werden. Falls noch nicht über solche Software verfügen, finden Sie diese im Internet.

Beachten Sie bitte die Systemvoraussetzungen und Kompatibilitätshinweise.

Schritt-für-Schritt Anleitung
  1. Stellen Sie mit Ihrem FTP-Programm eine Verbindung zu Ihrem Anbieter her.
  2. Kopieren Sie die Dateien "install.php", "install.pak" und "yana.zip" in ein Verzeichnis auf Ihren Server
  3. Setzen Sie die Zugriffsrechte für dieses Verzeichnis über Ihr FTP-Programm so, dass es dem Skript später möglich ist, Dateien zu lesen oder zu speichern. Unter Unix mit dem Befehl CHMOD 777. (siehe Abbildung)
  4. Schließen Sie die FTP-Verbindung.
  5. Öffnen Sie die Datei "install.php" über Ihren Webbrowser

Sobald Sie das Installationsprogramm gestartet haben sollten Sie folgende Seite sehen:

Zum Fortfahren klicken Sie auf die Schaltfläche "weiter".

Um mit der Installation fortzufahren, müssen Sie die Lizenzbedingungen akzeptieren. Andernfalls, können Sie die Installation mit der unteren Schaltfläche abbrechen.

Klicken Sie auf die Schaltfläche "Installation jetzt starten". Klicken Sie anschließend auf "weiter".

Mit diesem Passwort können Sie das Administrationsmenü der Anwendung aufrufen. Verwenden Sie dazu den Login "Administrator". Das Passwort geben Sie bitte erst in das linke Feld ein und wiederholen das im rechten Feld. Klicken Sie anschließend auf "OK".

Es wird angezeigt, ob die Operation erfolgreich war oder nicht. Klicken Sie anschließend auf "weiter.

Um sicher zu gehen, dass die Installation erfolgreich war, können Sie eine Selbstdiagnose des Programms durchführen lassen. Klicken Sie dazu auf die Schaltfläche "OK".

Wenn Sie mit der Installation zufrieden sind, klicken Sie auf "weiter".

Nach Beendigung der Installation löscht das Programm selbstständig alle erzeugten temporären Dateien. Wenn Sie die Option "Anwendung jetzt starten" markieren, wird anschließend automatisch das YANA Framework aufgerufen.

Um die Installation zu beenden klicken Sie auf "Fertigstellen".

Variante 2: von Hand installieren

Beachten Sie bitte die Systemvoraussetzungen und Kompatibilitätshinweise.

Schritt-für-Schritt Anleitung
  1. die Programmdateien finden Sie im Archiv "yana.zip". Entpacken Sie diese Datei mit einem ZIP-Programm Ihrer Wahl.
  2. Stellen Sie mit Ihrem FTP-Programm eine Verbindung zu Ihrem Anbieter her.
  3. Laden Sie alle Dateien und Verzeichnisse, die zum Programm gehören, in einen Ordner auf Ihrer Homepage und verlinken Sie die Startseite "index.php" von einer beliebigen Seite Ihrer Homepage aus.
  4. Setzen Sie die Zugriffsrechte für die Verzeichnisse "config/", "cache/" und die darin enthaltenen Dateien INKLUSIVE der Unterverzeichnisse über Ihr FTP-Programm so, dass es dem Skript später möglich ist, Dateien zu lesen oder zu speichern. Unter Unix mit dem Befehl CHMOD 777. (siehe Abbildung)
  5. Schließen Sie die FTP-Verbindung.

Beispiel: Festlegen der Zugriffsrechte

Screenshot
Abbildung: WS_FTP LE, Win 2000
Screenshot
Abbildung: Firefox mit Add-on "FireFTP"

Wenn Sie ein anderes FTP-Programm verwenden, setzen Sie die Rechte über den FTP-Befehl CHMOD 777 . Oder versuchen Sie es über die Onlinehilfe Ihres Programms unter dem Stichwort "CHMOD".

Variante 3: manuelle Installation auf einem eigenen Server

Hinweis: Diese Anleitung richtet sich an fortgeschrittene Anwender.
Sollten Sie Probleme haben, lesen Sie bitte zuerst den Abschnitt für Einsteiger.

Die Installation erfolgt in mehreren Schritten:

  1. Dekomprimierung der bereitgestellten Archivdatei. Zu beachten ist, dass Groß- und Kleinschreibung berücksichtigt wird und die gespeicherten Dateipfade ebenfalls wiederhergestellt werden.
  2. Übertragung der dekomprimierten Daten unter Berücksichtigung der Pfadstruktur in das HTDOCS-Verzeichnis des Apache Webservers. Verwenden Sie dazu eine geeignete Software Ihrer Wahl. Sollten Sie direkt am Server arbeiten können, ist dies in der Regel entweder Kommandozeile oder ein Dateimanager. Andernfalls in der Regel ein FTP-Client. Die erforderlichen Einstellungen für die FTP-Verbindung erfragen Sie bitte bei Bedarf bei Ihrem zuständigen Administrator.
  3. Beachten Sie unter Unix- beziehungsweise unter Linux-Betriebssystemen, dass die Zugriffsrechte für die Software korrekt konfiguriert sind. Diese Software benötigt Leserechte für alle mitgelieferten Dateien und Verzeichnisse. Alle Dateien mit der Endung "php" müssen ausführbar sein. Darüber hinaus benötigt die Software Schreibrechte für die Verzeichnisse "config/", "cache/" und alle darin enthaltenen Dateien und Unterverzeichnisse.
  4. Die folgenden Schritte sind nur erforderlich, falls ein Datenbankplugin verwendet werden soll.
    1. Einrichten einer neuen Datenbank, sofern keine bereits existierende Datenbank verwendet werden soll. Dies kann zum Beispiel über eine geeignete grafische Oberfläche wie PHP MyAdmin erfolgen. Falls dies nicht zur Verfügung steht ist die Bereitstellung über die Kommandozeile von MySQL möglich verwenden Sie dazu folgende Zeile: "CREATE DATABASE guestbook". Die Datenbank kann eine andere Bezeichnung als die hier verwendete erhalten. Beachten Sie jedoch bitte Groß- und Kleinschreibung. Für weitere Details zur MySQL Syntax empfehle ich die Lektüre des kostenlos verfügbaren MySQL-Handbuchs. (siehe Literaturempfehlungen)
    2. Sofern kein geeigneter Nutzer für die betreffende Datenbank zur Verfügung steht, legen Sie bitte zu diesem Zweck einen neuen Nutzer an. Dieser Nutzer benötigt Zugriff auf die eben erstellte Datenbank sowie folgende Rechte: SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER. Verwenden Sie dazu die nachstehende SQL-Anweisung: "GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER ON '<Datenbankname>' . * TO "<Nutzername>"@"<Host>" IDENTIFIED BY '<Passwort>';". Passen Sie diese Anweisung an, sofern notwendig. Ersetzen Sie insbesondere den Namen der Datenbank den Nutzernamen, das Passwort und die Adresse des Datenbankservers ("Host") falls erforderlich entsprechend Ihrer aktuellen Konfiguration. Notieren Sie sich diese Daten für den späteren Gebrauch. Anmerkung: Sie können, falls dies gewünscht ist, dem Nutzer die Rechte "CREATE" und "ALTER" nach erfolgreicher Installation der Datenbank wieder entziehen.

Die wichtigsten Schritte zur Konfiguration der Anwendung:

  1. Rufen Sie die Startseite "index.php?action=index" mithilfe javascriptfähigen Webbrowser auf.
  2. Anmelden am System. Klicken Sie den Knopf mit der Aufschrift "Login" und melden Sie sich unter der Verwendung des Nutzernamen "Administrator" an. Lassen Sie das Feld "Passwort" bitte frei. (Zu Anfang ist noch kein Passwort festgelegt)
  3. Das Hauptmenü kennt zwei Einstellungen: Anfänger- und Expertenmodus. Sie sollten nun in den Expertenmodus wechseln. Nutzen Sie dazu den Schalter am Kopf der Tabelle.
  4. Oberhalb des Hauptmenüs finden Sie eine Menüleiste für die Profilverwaltung. Diese erlaubt das Anlegen von neuen Profilen, sowie das Auswählen von bestehenden Profilen. Außerdem finden Sie hier den Schalter zum Leeren des Template-Caches. Dieser bewirkt, dass alle im Verzeichnis "cache/" gespeicherten Dateien gelöscht werden. Dieser Schalter kann gelegentlich nützlich sein, falls das Programm sich nach einer Änderung der Einstellungen nicht wie erwartet verhält. Das Hauptmenü selbst untergliedert sich in 2 Spalten. In der rechten Spalte finden Sie eine Liste aller installierten Komponenten. Diese sind nach 3 Kategorien geordnet: Plugins, Skins und Sprachdateien. In der linken Spalte finden Sie alle Konfigurationseinstellungen der installierten Plugins. Der Inhalt dieser Spalte ändert sich dynamisch je nachdem welche Plugins bzw. Anwendungskomponenten installiert worden sind.
  5. Die folgenden Schritte sind nur erforderlich, falls ein Datenbankplugin verwendet werden soll.
    1. Wählen Sie aus der Profilleiste die "Basiseinstellungen" und klicken Sie anschließend in der linken Spalte auf den Schalter "Datenbank Setup".
    2. Geben Sie die erforderlichen Daten für die Verbindung zu Ihrem Datenbankserver ein. Diese Daten erhalten Sie bei Bedarf bei Ihrem Administrator. Beachten Sie die Hinweise der Online-Hilfe. (Dies ist der grau gedruckte Text oberhalb des Eingabeformulars.) Speichern Sie anschließend die vorgenommenen Änderungen. Eine detaillierte Anleitung mit Hinweisen zum Vorgehen im Fehlerfall finden Sie im Kapitel "Plugin: DB-Administration".
    3. Die erforderlichen Tabellen werden automatisch erzeugt und mit den Tabellen im Dateisystem synchronisiert. Falls Sie den Vorgang von Hand durchführen wollen, benutzen Sie bitte diese passenden SQL-Quelldateien für Ihr DBMS.
  6. Abschließend empfiehlt es sich für das Nutzerkonto "Administrator" ein Passwort zu vergeben. Wählen Sie zu diesem Zweck aus dem Menü "Optionen" den Eintrag "Passwort ändern". Geben Sie ein neues Passwort ein und speichern Sie die Änderungen. Anschließend müssen Sie sich mit dem neuen Passwort erneut am System anmelden.
  7. Optional empfiehlt es sich, individuelle Einstellungen für das Layout der Software vorzunehmen. Diese beeinflussen Aussehen und Verhalten der GUI. Die Optionen zum Editieren dieser Einstellungen finden Sie in der linken Spalte des Administrationsmenüs. Achten Sie auf die bereitgestellte Online-Hilfe der Software.
  8. Sollten Sie mit Ihren Einstellungen zufrieden sein, sollten Sie sich aus Sicherheitsgründen durch Klicken auf den Knopf "Logout" vom System abmelden. Dadurch wird Ihre aktive Session terminiert. Dies verhindert potentielle Angriffe durch Dritte unter Verwendung Ihrer Session-ID. ("Session Riding")

SQL-Quelldateien für manuelle Installation:

weiterführende Literatur

  1. MySQL Online Dokumentation, http://dev.mysql.com/doc/
  2. Offizielle PHP Webseite, http://www.php.net
  3. PHP Security - Manual http://www.php.net/manual/en/security.php

Erster Login

Administrationsmenü öffnen

Öffnen Sie in Ihrem Browser die Datei "index.php?action=index" im Verzeichnis des Programms.
Sie werden aufgefordert, sich am System anzumelden und einen Login, sowie das dazu gehörige Passwort einzugeben. (siehe Abbildung)

Login: Administrator Passwort:
Geben Sie als "Login" den Text "Administrator" ein.

Falls Sie während der Installation bereits ein Passwort festgelegt haben, müssen Sie dieses nun eingeben.
Sollten Sie das Passwort vergessen haben, lesen Sie bitte im Abschnitt "häufig gestellte Fragen" weiter.

Bestätigen Sie Ihre Eingabe mit Klick auf "OK". Achten Sie bitte darauf, dass JavaScript in Ihrem Browser aktiviert sein sollte, damit die folgende Seite korrekt dargestellt werden kann.

Passwort ändern

altes Passwort: neues Passwort: ********

• Tipp: Um zu verhindern, dass jemand Ihr Passwort erraten kann, sollte es mindestens eine Länge von 8 Zeichen haben und mindestens 2 Sonderzeichen enthalten. Leicht zu erraten sind zum Beispiel Geburtstage, Namen von Personen oder Tieren und Begriffe, welche in handelsüblichen Wörterbüchern zu finden sind.

Schritt-für-Schritt Anleitung
  1. Scrollen Sie mit der Maus zum Abschnitt "Passwort ändern".
  2. Falls Sie während der Installation noch kein Passwort festgelegt haben, können Sie das Feld "altes Passwort" frei lassen.
    Ansonsten geben Sie Ihr altes Passwort hier ein.
  3. In das Feld "neues Passwort" schreiben Sie bitte einen beliebigen Text, welchen Sie als Passwort verwenden möchten. (siehe Abbildung)
  4. In das Feld "Passwort bestätigen" geben Sie den gleichen Text noch einmal ein, um sicher zu gehen, dass Sie sich nicht vertippt haben.
  5. Klicken Sie auf den Schalter "Änderungen speichern".
  6. Abschließend werden Sie aufgefordert, sich mit Ihrem neuen Passwort erneut am System anzumelden.

Notieren Sie sich Ihr neues Passwort und heben Sie es gut auf.

• Fehlermeldung? Wenn die Zugriffsrechte nicht gesetzt wurden, wie bei der "Installation" beschrieben, wird an dieser Stelle eine Fehlermeldung angezeigt. Lesen Sie in diesem Fall noch einmal nach, was Sie tun müssen und folgen Sie der Anleitung.

Weitere Tipps:
  1. Klicken Sie im Administrationsmenü auf den Schalter "zu Expertenmodus wechseln" um erweiterte Optionen zu erhalten
  2. Klicken Sie auf das kleine Symbol mit dem rot/weißen "i" um zusätzliche Informationen zu einem Menü ein-/ oder auszublenden
  3. Damit Menüs geöffnet oder geschlossen werden können, muss JavaScript aktiviert sein
  4. Um die Sicherheit zu erhöhen denken Sie bitte daran im Hauptmenü auf den Schalter "Logout" zu klicken, wenn Sie Ihre Einstellungen beendet haben
  5. Klicken Sie im Hauptmenü auf den Namen eines Plugins, einer Sprachversion oder eines Skins, um eine Beschreibung zu erhalten

Das Administrationsmenü verwenden

Das Administrationsmenü bietet einen Anfänger- und einen Expertenmodus. Einige Optionen sind nur im Expertenmodus sichtbar. Um vom Anfänger- in den Expertenmodus zu wechseln, klicken Sie auf den Link "zu Expertenmodus wechseln".

Link: zu Expertenmodus wechseln
Abbildung: Position des Links zum Umschalten des Betriebsmodus

Einstellungen im Anfängermodus

Administrationsmenü im Anfängermodus
Abbildung: Optionen des Administrationsmenüs im Anfängermodus

Hinweis: Installierte Plugins können nur im Expertenmodus aktiviert oder deaktiviert werden.

Einstellungen im Expertenmodus

Administrationsmenü im Expertenmodus
Abbildung: Optionen des Administrationsmenüs im Expertenmodus

Arbeiten mit mehreren Anwendungsprofilen

Das Programm verfügt über eine Profilverwaltung, welche es gestattet, mehrere Sätze von Einstellungen (Profile) gleichzeitig zu betreiben. Verwenden Sie dies, um mehrere Layouts/Webseiten/Abteilungen/Fillialen mit der gleichen Installation und verschiedenen Einstellungen zu betreiben.

Beispiel: Dieses Programm kann beliebig vielen Nutzern gleichzeitig jeweils eigene Instanzen der Anwendung zur Verfügung stellen. Bspw. um jedem Nutzer ein eigenes Gästebuch zuzuordnen. Damit diese unterschieden werden können, hat jede Instanz eine ID welche sie eindeutig identifiziert. Diese Id finden Sie auch in der URL des Browsers, als optionalen Parameter "id".

Über die Option "neues Profil anlegen" können Sie neue Profile erzeugen. Um neue Profile erzeugen zu können, müssen Sie über Administratorrechte verfügen.

Falls ein Profil aufgerufen wird, dass noch nicht existiert, werden wahlweise Defaultwerte verwendet, oder ein Fehler gemeldet. Dies ist abhängig von der Einstellung "Community-Freigabe" welche Sie im Menü "Programmsetup" finden. Die Defaultwerte sind im Profil mit dem Namen "Basiseinstellungen" gespeichert.

Um das Profil "Basiseinstellung" (oder ein anderes) zu öffnen, klicken Sie auf "Profil wechseln". (siehe Abbildung)

Basiseinstellungen

Die Basiseinstellungen gelten automatisch für alle aufgerufenen Profile, sofern keine anderen Einstellungen festgelegt sind. Außerdem gelten Sie für alle neu angelegten Profile. Achtung: einige Plugins können Optionen besitzen, die entweder NUR, oder aber überall AUSSER in den Basiseinstellungen abgerufen werden können.

Häufig gestellte Fragen

Ich habe Probleme mit der automatischen Installation. Kann ich das Programm manuell installieren?

Beachten Sie die Systemvoraussetzungen und lesen Sie den Abschnitt "manuelle Installation".

Was kann ich tun, wenn bei der Konfiguration der Datenbankverbindung ein Fehler auftritt?

Bitte prüfen Sie zunächst, ob Ihre Verbindungsparameter korrekt sind und der Datenbankserver erreichbar ist. Beachten Sie auch die Kompatibilitätshinweise, da sich darunter Informationen und Lösungshinweise zu typischen Schwierigkeiten mit einigen DBMS befinden.

Sollten die Verbindungsparameter korrekt sein und auch kein Problem mit dem Datenbanktreiber oder ein Versionskonflikt vorliegen, können Sie das Problem durch eine manuelle Installation umgehen. Lesen Sie dazu die Anleitung für den Fehlerfall.

Beachten Sie, dass PEAR, PEAR MDB2 und der passende MDB2-Datenbanktreiber, sowie der Datenbanktreiber für PHP installiert sein müssen, um eine Verbindung herstellen zu können.

Wenn ich die Datei "index.php" aufrufe wird nur der Quellcode angezeigt. Warum?

Dieses Skript benötigt PHP. Wenn der Quellcode im Browser angezeigt wird dann kann es sein, dass PHP von ihrem Anbieter nicht unterstützt wird. Fragen Sie im Zweifel ihren Anbieter.

vergessene Passwörter

Wenn Sie als normaler Nutzer Ihr Passwort vergessen haben, schreiben Sie eine Mail an Ihren Administrator. Dieser kann ein neues Passwort für Sie festlegen.

Administratoren gehen wie folgt vor um ein neues Passwort festzulegen:

  1. Öffnen Sie das Administrationsmenü.
  2. Im Menü "Nutzerverwaltung" / "Nutzerübersicht" finden Sie eine Liste aller Nutzer.

    Nutzerübersicht: hier klicken
    Abbildung: Menü "Nutzerübersicht"

  3. Anschließend wird Ihnen eine Liste aller Nutzer angezeigt. Suchen Sie den Namen des Nutzers, welchen Sie bearbeiten wollen und klicken Sie auf das Symbol in der Spalte "Nutzername".

    Nutzer editieren: klicken Sie hier um Details für diesen Nutzer anzuzeigen
    Abbildung: Liste aller Nutzer

  4. Unterhalb der Einstellungen finden Sie den Link "Passwort vergessen". Klicken Sie auf diesen Link um ein neues Passwort generieren zu lassen. Das neue Passwort wird dem Nutzer via Mail zugesandt. Achten Sie daher darauf, dass die Mailadresse korrekt ist.

    Nutzer editieren: neues Passwort generieren
    Abbildung: neues Passwort generieren

Falls Sie Ihr eigenes Passwort vergessen haben, wenden Sie sich an einen anderen Administrator. Falls Sie selbst der Administrator sind, dann kann kein neues Passwort generiert werden. Sie haben aber die Möglichkeit das alte Passwort von Hand zu löschen.

Falls die Installation mit Textdateien arbeitet, verbinden Sie sich bitte via FTP mit Ihrem Konto und laden Sie die Datei "config/db/user/user.sml" herunter. Editieren Sie diese Datei und ersetzen Sie das Passwort durch den Text "UNINITIALIZED". Laden Sie die Datei dann wieder hoch und setzen Sie die Zugriffsrechte mit CHMOD 777.

Falls die Installation mit einer Datenbank arbeitet, verbinden Sie sich mit Hilfe eines geeigneten Programms (zum Beispiel PHPmyAdmin für MySQL) mit der Datenbank und editieren Sie die Tabelle "user" und setzen Sie für den Nutzer "ADMINISTRATOR" das Passwort auf "UNINITIALIZED".
Alternativ können Sie auch einfach folgende SQL-Anweisung ausführen.
UPDATE `user` SET user_pwd = 'UNINITIALIZED' WHERE user_id = 'ADMINISTRATOR';
(Quotes bitte für das von Ihnen verwendete DBMS anpassen)

Denken Sie bitte daran, anschließend ein neues Passwort festzulegen.

Beispiel Hinweis: Das echte Passwort wird von diesem Skript niemals als reiner Text gespeichert. Nach der Eingabe wird es stattdessen verschlüsselt. Diese Verschlüsselung funktioniert nur in eine Richtung und ist nicht umkehrbar. Aus diesem Grund ist es nicht möglich, einem Nutzer das von ihm vergessene Passwort zu nennen, sondern es muss stets ein neues erstellt werden.

eigene Smilies und Icons einfügen

Suchen Sie die Smilies aus, welche Sie einfügen möchten. Achten Sie bitte darauf, dass diese Grafiken im GIF-Format gespeichert sind.

Kopieren Sie anschließend diese Dateien in das Verzeichnis " common_files/smilies " des Frameworks.

Wenn Sie die Smilies von einem anderen Verzeichnis als dem vorgegebenen laden wollen, gehen Sie wie folgt vor.

  1. Öffnen Sie das Administrationsmenü.
  2. Wechseln Sie in den Expertenmodus.
  3. Klicken Sie in der linken Spalte des Hauptmenüs "Optionen" auf "Pogrammsetup".
  4. Suche Sie den Eintrag "Emoticons laden von". (siehe Abbildung)
  5. Geben Sie dort das gewünschte Verzeichnis ein.
  6. Klicken Sie abschließend auf "Änderungen übernehmen".

Sollten Sie mehrere Profile verwenden, müssen Sie evtl. die Einstellungen für alle weiteren Profile ebenfalls editieren.


Abbildung: Icons von einem anderen Verzeichnis laden

Probleme mit der Installation

Lesen Sie den Abschnitt " Installation für Anfänger ". Das Programm verfügt ab Version 2.2 über einen Selbstdiagnosemodus. Falls Sie die Installation wie in der Anleitung beschrieben durchgeführt haben, können Sie damit prüfen, ob alle Dateien korrekt installiert sind.

Um den Selbstdiagnosemodus zu starten, rufen Sie in Ihrem Browser das Programm mit der URL "index.php?action=test" auf. Das Programm wird dann damit beginnen, ein Diagnoseprotokoll zu erstellen. Der Selbstdiagnosemodus testet dabei Verzeichnisse und wichtige Dateien und meldet Fehler. Diese werden als rot markierte Zeilen im Protokoll dargestellt. Falls ein Fehler gefunden wird, lesen Sie die Fehlermeldung und befolgen Sie die Anweisungen.

Der Selbstdiagnosemodus findet einige der typischen Installationsfehler, kann aber selbstverständlich nicht alle möglichen Fehler finden. Falls Sie das Programm nach Anleitung installiert haben und trotzdem Probleme haben es in Betrieb zu nehmen, senden Sie mir am besten eine Mail an . Vergessen Sie nicht die URL anzugeben und eine Beschreibung Ihres Problems. Dieses Angebot ist für registrierte Nutzer kostenlos.

Verwendung des Datenbankpräfixes

Das Datenbank-Setup bietet eine Option "Präfix der Datenbank" (siehe Abbildung). Diese Option IST EXPERIMENTELL und dient ausschließlich dem Zweck, zwei Installationen des YANA Framework auf dem gleichen Server und der gleichen Datenbank arbeiten zu lassen, ohne dass diese sich gegenseitig beeinflussen. In allen Situationen, wo sie nicht benötigt wird, wird wegen ihres experimentellen Status dringend empfohlen, diese Option NICHT zu verwenden.


Abbildung: experimentelle Option zum Setzen eines Präfixes für die Datenbankverbindung

Eine typische Anwendung für diese Option wäre, dass Sie von einer älteren auf eine neue Version umsteigen möchten und deshalb vorübergehend zu Testzwecken zwei Installationen betreiben möchten, um die neue Version im realen Umfeld zu testen, bevor Sie umsteigen.

Falls Sie ein Präfix angeben, bedeutet dies auch, dass Sie die SQL-Installationsdateien im Verzeichnis "config/db/.install" von Hand so korrigieren müssen, dass die Tabellen entsprechend des von Ihnen gewählten Präfixes benannt sind. Erst danach können Sie die Datenbank wie gewohnt installieren. Für diese Änderung steht zur Zeit noch keine automatische Behandlung zur Verfügung. Den PHP-Quellcode müssen Sie jedoch nicht ändern.

Falls Sie von Ihnen selbst geschriebene Plugins mit handgeschriebenen SQL-Anweisungen verwenden, müssen Sie selbstverständlich auch dort den Quellcode so anpassen, dass die veränderte Benennung der Tabellen berücksichtigt wird. Sollten Sie jedoch die Datenbank-API des Frameworks verwenden und sich Ihre SQL-Anweisungen automatisch erzeugen lassen, dann ist das Editieren der Dateien nicht notwendig. Das Framework passt Ihr SQL zur Laufzeit automatisch an.

Für die Umstellung der SQL-Installationsdateien sollten Sie 5 bis 15 Minuten einplanen.

Falls Sie diese Option versehentlich verwendet und Probleme mit dem Zugriff auf Ihre Daten haben sollten, dann können Sie die Einstellung von Hand zurücksetzen. Editieren Sie dazu bitte die Datei "config/dbconfig.php" und ändern Sie den Eintrag in Zeile 9 zu: define('YANA_DATABASE_PREFIX',"");

Anmerkung: in einigen Versionen der Anwendung ist dieses Feature absichtlich deaktiviert.

Sitemap abschalten

Falls Sie nicht die Sitemap als Startseite der Anwendung verwenden möchten, ist es möglich diese durch eine andere Seite zu ersetzen - beispielsweise die Startseite eines Plugins Ihrer Wahl.

Öffnen Sie dazu die Datei "config/system.config.xml" in einem Texteditor Ihrer Wahl und ändern Sie den Eintrag "DEFAULT.HOMEPAGE" entsprechend Ihren Wünschen ab (siehe Abbildung).


Abbildung: Ändern der Startseite (Default-Homepage)

Formatierung von Texten ohne HTML

Falls Sie keine HTML-Eingabe erlauben wollen, haben Sie die Möglichkeit auf EmbTags zur Formatierung von Einträgen zurückzugreifen.

Welche Möglichkeiten gibt es?
Icon Tags Beschreibung Beispiel Ausgabe
[b] [b] Text fett formatieren [b]fetter Text[/b] fetter Text
[i] [i] Text kursiv formatieren [i]kursiver Text[/i] kursiver Text
[u] [u] Text unterstreichen [u]unterstrichener Text[/u] unterstrichener Text
[code] [code] Quellcodes einfügen
(Code wird nicht ausgeführt, sondern als Text formatiert)
[code]Text[/code] Text
[php] [php] PHP-Quellcodes einfügen
(Code wird nicht ausgeführt, sondern als Text formatiert)
[php]print 'Hallo Welt';[/php]
<?php
print 'Hallo Welt';
?>
[color] [color] legt die Textfarbe fest [color=red]Text[/color] Text
[mark] [mark] legt die Hintergrundfarbe fest (Textmarker) [mark=yellow]Text[/mark] Text
[url] [url] Hyperlink einfügen [url]www.yanaframework.net[/url] www.yanaframework.net
[mail] [mail] Mailadressen einfügen [mail]mail@domain.tld[/mail] mail@domain.tld
[img] [img] Grafiken einfügen * [img]domain.tld/img/image.gif[/img] [img]
[emp] [emp] Text hervorheben [emp]Text[/emp] Text
[header] [h] Überschrift einfügen [h]Überschrift[/h]
Überschrift
[small] [small] reduziert die Schriftgröße [small]kleiner Text[/small] kleiner Text
[big] [big] erhöht die Schriftgröße [big]großer Text[/big] großer Text
[c] [c] fügt einen Kommentar ein
(zum Beispiel zum Schreiben von Signaturen)
[c]Kommentar[/c]
Kommentar
[hide] [hide] verbirgt einen Text, bis der Nutzer mit der Maus darüber fährt [hide]das ist ein Geheimnis[/hide]
das ist ein Geheimnis
[wbr] [wbr] erlaubt Zeilenumbruch innerhalb eines Wortes Schiff[wbr]fahrts[wbr]angestellte Schifffahrts
angestellte
[br] [br] erzwingt Zeilenumbruch Schiff[br]fahrts[br]angestellte Schiff
fahrts
angestellte

Codebeispiele

Um eine Symbolleiste einzublenden:
{%embeddedTags%}



Um Embedded-Tags in HTML zu konvertieren:
{%$text|embeddedTags%}

* YANA unterbindet Angriffe auf Ihre Website durch Cross-Site-Scripting (XSS), weil es nur das Einbinden von Grafiken gestattet, die auf dem lokalen Server im Verzeichnis des Frameworks liegen. Die Datei muss außerdem eine der Dateiendungen "jpeg","jpg","png", oder "gif" besitzen. Sonderzeichen sind nicht gestattet; dadurch wird verhindert, dass ein Angreifer die wahre URL einer Datei durch den geschickten Einsatz von Escapesequenzen verschleiern kann, um sich so am Schutz des Frameworks vorbei zu schmuggeln.

Der Tag [img] ist sinnvoll für Community-Websites, die Ihren Nutzern den Upload eigener Grafikdateien auf den Server gestatten.

Eigene Embedded-Tags definieren

Beispiel Warnung: Fehlerhafte Einstellungen können unter Umständen dazu führen, dass das Programm nicht mehr korrekt ausgeführt werden kann. Führen Sie derartige Änderungen daher niemals direkt an einem Produktivsystem durch, sondern prüfen Sie Ihre Einstellungen unbedingt zuvor in einer Testumgebung.

Es ist möglich, für jedes Website-Profil individuelle Tags festzulegen. Dazu gehen Sie wie folgt vor.

  1. Öffnen Sie das Verzeichnis "config/profiles"
  2. Wählen Sie das Profil, welche Sie editieren wollen (zum Beispiel "default.config") und öffnen Sie diese Datei in einem Texteditor Ihrer Wahl
  3. Ergänzen Sie den Container "PROFILE" wie folgt.
    Erläuterung der Syntax:
    <PROFILE>
    ...
    <
    EMBTAG>
    <tagname>
    <
    TITLE>Wert des Attributes "title"</TITLE>
    <
    TEXT>Benennung</TEXT>
    <
    IMAGE>Bild der Schaltfläche, welche den Tag einfügt</IMAGE>
    <
    1>optionaler regulärer Ausdruck zum Umwandeln in HTML</1>
    (Defaultwert = /\[$tagname\](.*)(?:\[\/$tagname\]|$)/Us)
    <
    2>optionaler Ersatzstring zum Umwandeln in HTML</2>
    (Default = &lt;span class="embtag_tag_{tagname}"&gt;$1&lt;/span&gt;)
    </tagname>
    </
    EMBTAG>
    </
    PROFILE>
    Zum Vergleich folgendes Beispiel für den Tag "bold":
    <PROFILE>
    ...
    <
    EMBTAG>
    <bold>
    <
    TITLE>Einfügen von fett formatiertem Text</TITLE>
    <
    TEXT>fetter Text</TEXT>
    <
    IMAGE>%SKINDIR%/default/styles/tags/b.gif</IMAGE>
    <
    1>/\[bold\](.*)\[\/bold\]/Us</1>
    <
    2>&lt;b&gt;$1&lt;/b&gt;</2>
    </bold>
    </
    EMBTAG>
    </
    PROFILE>
  4. Speichern Sie Ihre Änderungen.
  5. Testen Sie die Verwendung Ihres neuen Tags an einem eigenen Formular

Beispiel Hinweis: Wenn Sie einen Tag entfernen, so wird der Tag nicht mehr als HTML dargestellt. Dies betrifft auch solche Daten, welche diesen Tag bereits früher enthalten haben. Beachten Sie auch, dass Sie die Originaltags nicht entfernen oder ersetzen können.

Meine Frage war nicht dabei - was kann ich tun?

Melden Sie sich mit Ihrer Frage im Internetforum unter yanaframework.net/forum.

Erweiterungen

Skins installieren

Ein "Skin" ist ein Paket von angepassten Musterseiten und Grafiken. Dieses Paket ändert die Eingabeoberfläche - also das "Look & Feel" Ihrer Anwendung.

  1. Entpacken Sie das Archiv, welches den Skin enthält in das Skinverzeichnis der Anwendung. (Standard: "skins/")
  2. Öffnen Sie Ihr Administrationsmenü. Stellen Sie sicher, dass Sie als Administrator angemeldet sind und den Expertenmodus aktiviert haben.
  3. Im Abschnitt "installierte Skins" sollten Sie den Namen des neu installierten Pakets lesen können.
  4. Wählen Sie das gewünschte Paket durch Anklicken des Radiobutton (runder Knopf) aus, der neben dem Namen angezeigt wird.  (siehe Abbildung)
  5. Wenn Sie fertig sind, klicken Sie auf "Änderungen speichern".

Skin wählen

Die Änderungen werden beim nächsten Aufruf des Programms aktiv. Sollte der Skin unerwartet nicht aktualisiert werden, leeren Sie im Administrationsmenü den Server-Cache und versuchen Sie es erneut.

Tipps zur Fehlerbehebung

  1. Falls Sie kein Menü "installierte Skins" sehen können, haben Sie vermutlich den Expertenmodus nicht aktiviert
  2. Falls Sie das Menü, aber keinen Radiobutton sehen können, haben Sie keine ausreichenden Rechte für die Installation. Bitten Sie daher einen Administrator darum die Installation für Sie durchzuführen.
  3. Falls Sie die Änderungen nicht speichern können, ist eventuell eine Datei im Verzeichnis "config/" schreibgeschützt. Korrigieren Sie die Zugriffsrechte und versuchen Sie es erneut.

Plugins installieren

Plugins erweitern Ihre Anwendung um neue Funktionen.

  1. Entpacken Sie das Archiv, welches das Plugin enthält in das Verzeichnis "plugins/" der Anwendung. Achten Sie darauf keine Dateien zu überschreiben, es sei denn, Sie sind gerade dabei ein Plugin auf eine neuere Version zu aktualisieren.
  2. Öffnen Sie Ihr Administrationsmenü. Stellen Sie sicher, dass Sie als Administrator angemeldet sind und den Expertenmodus aktiviert haben.
  3. Klicken Sie auf die Schaltfläche "Liste neu laden". (siehe Abbildung)
  4. Das neue Plugin wird nun in der Liste erscheinen. Aktivieren Sie es, indem Sie die Checkbox links neben dem Namen anklicken.
  5. Wenn Sie fertig sind, klicken Sie auf "Änderungen speichern".
  6. Manche Plugins haben zusätzliche Optionen. Diese Optionen erscheinen nach der Aktivierung automatisch.

Um das Plugin später wieder zu deaktivieren, wiederholen Sie die Prozedur und entfernen den Haken von der Checkbox links neben dem Namen des Plugins.

Liste der verfügbaren Plugins

Tipps zur Fehlerbehebung

  1. Falls Sie kein Menü "Plugins" sehen können, haben Sie vermutlich den Expertenmodus nicht aktiviert
  2. Falls Sie das Menü, aber keinen Checkboxes sehen können, haben Sie keine ausreichenden Rechte für die Installation. Bitten Sie daher einen Administrator darum die Installation für Sie durchzuführen.
  3. Falls Sie die Änderungen nicht speichern können, ist eventuell eine Datei im Verzeichnis "config/" schreibgeschützt. Korrigieren Sie die Zugriffsrechte und versuchen Sie es erneut.

Sprachpakete installieren

Sprachpakete enthalten Übersetzungen der Textmeldungen der Anwendung in verschiedene Sprachen. Beispielsweise Deutsch oder Englisch.

  1. Entpacken Sie das Archiv, welches das Sprachpaket enthält in das Verzeichnis "languages/" der Anwendung. Achten Sie darauf keine Dateien zu überschreiben, es sei denn, Sie sind gerade dabei ein Paket auf eine neuere Version zu aktualisieren.
  2. Eine Liste der installierten Sprachpakete finden Sie im Administrationsmenü (siehe Abbildung).

Sprachpaket auswählen

Die Änderungen werden beim nächsten Aufruf des Programms aktiv.

Plugin: Gästebuch

Allgemeines

Dieses Plugin bietet Ihnen die Möglichkeit ein Gästebuch in Ihre Webseite einzubauen. Über diese Software können Ihnen Ihre Besucher Nachrichten hinterlassen. Diese Nachrichten sind für alle Besucher sichtbar. Sie haben die Möglichkeit, sich bei neuen Einträgen per Mail informieren zu lassen. Außerdem sind die neuesten Nachrichten als RSS-Feed abrufbar.

Plugin installieren

  1. Öffnen Sie das Administrationsmenü als Nutzer "Administrator" im Expertenmodus.
  2. Klicken Sie auf die Schaltfläche "Liste neu laden" um die Liste der installierten Plugins neu zu laden. (siehe Abbildung)
  3. Aktivieren Sie (falls vorhanden) die Plugins "DB-Administration", "Gästebuch" und "Gästebuch Setup". Speichern Sie anschließend Ihre Änderungen.
  4. Nach erfolgreicher Installation erscheint automatisch der Eintrag "Gästebuch" in der Sitemap der Anwendung.

E.-Mailbenachrichtigungen

Klicken Sie in Administrationsmenü auf "Gästebuch Setup". Im Abschnitt "E.-Mailbenachrichtigungen" können Sie festlegen, ob Sie bei neuen Einträgen automatisch per E.-Mail informiert werden wollen. Diese Option ist standardmäßig deaktiviert. Um diese zu aktivieren, klicken Sie auf den Schalter mit dem Text "aktivieren" und geben Ihre E.-Mailadresse in das Feld "Mail senden an" ein. (siehe Abbildung)

Um Ihre Änderungen zu speichern klicken Sie auf den Schalter "Änderungen speichern", oder klicken Sie auf "Abrechen", um zum Administrationsmenü zurückzukehren, ohne die Änderungen zu übernehmen.

Menü zur Einstellung von E.-Mailbenachrichtigungen
Abbildung: Basiseinstellungen editieren

mehrere Gästebücher

Das Programm legt normalerweise neue Gästebücher bei Bedarf automatisch an. Dabei werden Basiseinstellungen verwendet, welche für alle Gästebücher gleichermaßen gelten (siehe oben). Falls Sie möchten, dass ein Gästebuch ein ganz spezielles Profil von Einstellungen verwendet, welche von den Basiseinstellungen aller anderen Gästebücher abweichen, gehen Sie wie folgt vor:

  1. Öffnen Sie in Ihrem Browser das Administrationsmenü.
  2. Wählen Sie in der Profilverwaltung "neues Profil anlegen". Suchen Sie sich einen passenden Namen für Ihr Gästebuchprofil aus, den Sie in das Feld eingeben und speichern Sie das neue Profil. Das Profil wird anschließend automatisch ausgewählt.
  3. Um die Einstellungen des soeben erstellen Profils zu editieren, wählen Sie den Menüpunkt "Gästebuch Setup".

Ihr neues Gästebuch verlinken Sie so:

index.php?id=foo&action=guestbook_read

Wobei Sie statt "foo" den Namen Ihres Gästebuches einsetzen.

mehrere Layouts für das gleiche Gästebuch

  1. Öffnen Sie in Ihrem Browser das Administrationsmenü. Achten Sie darauf, dass Sie als Administrator angemeldet sind und dass der Expertenmodus aktiviert ist.
  2. Wählen Sie das Profil aus, welchen Sie anpassen wollen (verwenden Sie nicht die Basiseinstellungen).
  3. Öffnen Sie die Option "Programmsetup".
  4. Im Abschnitt "Datenquelle" gibt es den Eintrag "Daten verwenden von". Dort geben Sie bitte den Namen des Profils an, auf welches sich das Layout bezieht. Zum Beispiel: wenn Sie das Layout für das Gästebuch mit der Id "default" verwenden möchten, dann schreiben Sie: " default ".  (siehe Abbildung)

Daten von anderem Profil verwenden
Abbildung: Daten von anderem Profil verwenden

Genau so gehen Sie vor mit allen weiteren Layouts, die Sie erzeugen wollen.

Jedes neue Layout verlinken Sie genau so, wie ein echtes Gästebuch:

index.php?id=foo&action=guestbook_read

Wobei Sie statt "foo" den Namen des gewünschten Layouts einsetzen.

Schutz vor unerwünschter Werbung

Um Ihr Gästebuch vor unerwünschter Werbung zu schützen stehen Ihnen verschiedene Sicherheitsoptionen zur Verfügung. Über das Menü "Gästebuch Setup" können Sie die maximale Anzahl der Einträge pro Person begrenzen.

Spamschutz
Abbildung: Spamschutz

  1. Öffnen Sie in Ihrem Browser das Administrationsmenü. Achten Sie darauf, dass Sie als Administrator angemeldet sind und dass der Expertenmodus aktiviert ist.
  2. Öffnen Sie die Option "Gästebuch Setup".
  3. Scrollen Sie nun zum Abschnitt "Spamschutz". Hier können Sie mit Hilfe der Auswahlbox die Anzahl der Einträge, welche eine Person nacheinander schreiben darf begrenzen.

Zusätzliche Sicherheitseinstellungen bietet Ihnen die Verwendung des Plugins "Anti-Spam". Diese können Sie konfigurieren über das Menü "Anti-Spam Setup".

Liste der wichtigsten Datenfelder für Entwickler

Um die volle Liste zu sehen oder neue Felder einzufügen bzw. alte Felder zu löschen, öffnen Sie die passende Strukturdatei "config/db/guestbook.db.xml".

Feldname Typ Pflichtfeld Defaultwert Beschreibung
GUESTBOOK_ID integer ja <auto increment> Primärschlüssel
PROFILE_ID string nein default Schlüssel des passenden Profils.
GUESTBOOK_IP string nein <remote address> IP des Autors eines Beitrages.
GUESTBOOK_NAME string ja - Name des Autors
GUESTBOOK_MESSAGE string ja - Text des Beitrages
GUESTBOOK_MAIL string nein null Mailadresse des Autors eines Beitrages.
GUESTBOOK_DATE integer ja <current timestamp> Erstellungsdatum eines Beitrages.
GUESTBOOK_COMMENT string nein null Kommentar des Webmasters.

Plugin: Anti-Spam

Allgemeines

Dieses Plugin bietet Schutz vor unerwünschter Werbung. Dieser Schutz wirkt sich automatisch auf alle installierten Plugins aus. Die Konfiguration erfolgt über ein zusätzliches "Setup"-Plugin. Dieses fügt dem Administrationsmenü den Menüpunkt "Anti-Spam Setup" hinzu. Über dieses Menü ist es möglich Einstellungen vorzunehmen.

Einstellungen


Um Einstellungen vorzunehmen, gehen Sie wie folgt vor.

  1. Öffnen Sie in Ihrem Browser das Administrationsmenü.
  2. Öffnen Sie die Option "Anti-Spam Setup".
  3. Hier können Sie unter Anderem ein sogenanntes "CAPTCHA" aktivieren. Dadurch wird eine Grafik mit einem Text eingeblendet, welchen ein Nutzer abtippen muss, bevor er einen Beitrag abschicken darf.  (siehe Abbildung) Um das "CAPTCHA" verwenden zu können, muss die PHP GD-Bibliothek installiert und der PNG-Support aktiviert sein. Dies ist bei einer Standardinstallation von PHP üblicherweise der Fall. Sollte dies aus irgendwelchen Gründen bei Ihnen nicht der Fall sein, bitten Sie Ihren Administrator die fehlende Bibliothek nachträglich zu installieren. Erfahrungsgemäß ist dies bei den meisten Anbietern problemlos möglich.

    Anti-Spam Setup
    Abbildung: Anti-Spam Setup

  4. Wählen Sie mindestens die Sicherheitsstufe "mittel", falls Sie das CAPTCHA verwenden möchten.
    Die folgende Abbildung zeigt ein CAPTCHA am Beispiel des Gästebuch-Plugins.
  5. Sie können die Stufe "benutzerdefiniert" verwenden, um die Einstellungen selbst festzulegen.

Darstellung des CAPTCHA im Programm
Darstellung eines CAPTCHA im Programm. Hier: das Gästebuch-Plugin

  1. CAPTCHA ist eine eng. Abk. für (frei übersetzt) "eine Methode, um zwischen Computern und menschlichen Nutzern zu unterscheiden"

Plugin: DB-Administration

Allgemeines

Dieses Plugin erlaubt es Ihnen, die Verbindungseinstellungen zu Ihrer Datenbank zu editieren. Weiterhin können Sie Tabellen installieren, erforderliche Daten übertragen und Backups erstellen.

Verbindung zur Datenbank herstellen

Formular
Abbildung: Einstellungen der Verbindung zur Datenbank

Wählen Sie für die Option "Datenbank benutzen" den Wert "ja", um die eine Datenbankverbindung mit den angegebenen Verbindungsdaten zu verwenden. Die Installation der Datenbank läuft automatisch ab. Sie müssen somit nur im Fehlerfall von Hand eingreifen.

Beim Aktivieren der Datenbank werden automatisch folgende Aktionen durchgeführt:
  1. Test der Verbindungsparameter
  2. Verbindung zur Datenbank öffnen
  3. alle erforderlichen Tabellen installieren
  4. alle Daten aus dem Dateisystem zur Datenbank übertragen

Sollte an einem dieser Punkte ein Fehler auftreten, so wird die Verbindung NICHT aktiviert und es wird eine Fehlermeldung angezeigt. Eine genaue Erläuterung des Fehlers finden Sie im Fehlerprotokoll. Beachten Sie bitte, dass dazu die Protokollierung aktiviert sein muss (siehe Kapitel "Logging und Fehlermeldungen").

Anleitung für den Fehlerfall

Sie können im Fehlerfall die einzelnen Schritte, welche beim Aktivieren der Datenbankverbindung normalerweise automatisch durchgeführt werden, auch manuell durchführen. Gehen Sie dazu wie folgt vor.

  1. Prüfen Sie Ihre Verbindungseinstellungen auf Fehler. Falls diese korrekt sind, fahren Sie fort.
  2. Geben Sie die Verbindungsparameter zur Datenbank ein und speichern Sie Ihre Änderungen. Lassen Sie dabei aber den Wert der Option "Datenbank benutzen" unverändert auf "nein".
  3. Wählen Sie die Option "Datenbanken installieren". Versuchen Sie diese Aktion auszuführen, indem Sie auf "Abschicken" klicken (siehe Abbildung). Falls dies erfolgreich ist, fahren Sie mit dem nächsten Schritt fort.
    Sollte ein Fehler auftreten, prüfen Sie bitte mit einem anderen Programm, ob die Tabellen bereits existieren. Falls dies der Fall ist, löschen Sie die Tabellen und versuchen Sie es erneut.
    Falls die Tabellen nicht existieren, versuchen Sie die Tabellen mit einem anderen Programm zu installieren. Die Quellen dazu finden Sie in der "Installationsanleitung". Falls dies erfolgreich ist, prüfen Sie bitte erneut Ihre Verbindungseinstellungen.
  4. Wählen Sie die Option "Datenbanken synchronisieren". Versuchen Sie zunächst nur die Datenbank "user" zu synchronisieren. Deaktivieren Sie dazu alle anderen Optionen. Versuchen Sie danach die übrigen Datenbanken zu synchronisieren (siehe Abbildung). Sollte sich dabei ein Fehler ergeben, könnte die Ursache ein Datenfehler sein. Sie können sich dann entscheiden, ob sie auf die betroffenen Daten verzichten können. Sollte dies nicht möglich sein, so haben Sie die Möglichkeit die Daten entweder manuell in die Zieldatenbank zu kopieren, oder in der Quelldatenbank zu korrigieren.
    Sie finden die Quelldaten in Textdateien im Verzeichnis "config/db/name", wobei "name" für den Namen der Datenbank steht. Diese Maßnahme wird nur erfahrenen Nutzern empfohlen.
  5. Sollten die oben aufgeführten Schritte erfolgreich gewesen sein, so wählen Sie die Option "Verbindung zur Datenbank herstellen". Achten Sie darauf, dass Sie im Administrationsmenü den Expertenmodus aktiviert haben. Wählen für die Option "Datenbank benutzen" den Wert "ja". Deaktivieren Sie die Optionen "Tabellen automatisch anlegen" und "Datensätze kopieren". Diese Optionen sind nur im Expertenmodus sichtbar. Klicken Sie dann auf "Abschicken" (siehe Abbildung).

Bitte beachten Sie auch die Kompatibilitätshinweise!

Datenbanken installieren

• Hinweis: Dieser Schritt wird normalerweise automatisch ausgeführt, wenn eine Datenbankverbindung aktiviert wird. Das hier dargestellte Formular dient der manuellen Behandlung im Fehlerfall.

Formular
Abbildung: Formular zum installieren der Tabellen

Es wird versucht, die zu den ausgewählten Datenbanken gehörenden Tabellen auf dem Datenbankserver zu erzeugen. Zu diesem Zweck werden gespeicherte SQL Dateien importiert, passend zum Typ der Datenbank. Voraussetzung ist, dass die Verbindung zur Datenbank vorher korrekt konfiguriert worden ist. Sie sollten die Datenbankverbindung jedoch nicht aktivieren bevor sie die erforderlichen Tabellen erzeugt haben.

In seltenen Fällen kann dieser Prozess fehlschlagen. Z.Bsp. wenn: keine Verbindung zum Datenbankserver möglich ist, für das gewählte DBMS kein SQL erzeugt werden kann, das erzeugte SQL fehlerhaft ist, eine andere Tabelle mit der gleichen Bezeichnung bereits existiert, oder der Nutzer nicht ausreichende Rechte zum Erzeugen der Tabellen besitzt. In diesen Fällen muss die Installation von Hand durchgeführt werden.

Die erforderlichen SQL-Dateien für das manuelle Erzeugen der Tabellen finden Sie im Kapitel "Anleitung für Fortgeschrittene" / "Konfiguration".

Datenbanken synchronisieren

• Hinweis: Dieser Schritt wird normalerweise automatisch ausgeführt, wenn eine Datenbankverbindung aktiviert wird. Das hier dargestellte Formular dient der manuellen Behandlung im Fehlerfall.

Formular
Abbildung: Formular zum Kopieren der Inhalte der Tabellen zur Datenbank

Die Einträge in den Textdateien und der Datenbank werden miteinander abgeglichen. Bei diesem Vorgang werden KEINE Einträge gelöscht oder geändert, sondern lediglich neue hinzugefügt. Bei sehr großen Datenmengen kann es zu einem Timeout kommen. In diesem Fall wiederholen Sie die Prozedur mehrfach, bis alle Daten übertragen sind.

Backup erstellen

• Hinweis: Diese Option funktioniert nur wenn eine Datenbankverbindung aktiv ist.

Formular
Abbildung: Formular um ein Backup der Datenbank zu erstellen

Benutzen Sie diese Option um eine Sicherungskopie Ihrer Datenbank zu erstellen.

SQL-Syntax
der SQL-Dialekt, in welchem die Ausgabe gespeichert werden soll
Struktur exportieren
gibt an, ob die Tabellenstrukturen gespeichert werden sollen ("create table ...")
Daten exportieren
gibt an, ob die in den Tabellen enthaltenen Datensätze gespeichert werden sollen
als GZip komprimieren
da Backups sehr groß sein können, haben Sie die Möglichkeit mit dieser Option die Datei vor dem Herunterladen im GZip-Format zu komprimieren. Dadurch wird die Datei kleiner.

Plugin: Suchmaschine

Allgemeines

Mit diesem Skript können Sie Ihre Besucher den Inhalt Ihrer Homepage durchsuchen lassen. Um es verwenden zu können sind keine Programmierkenntnisse erforderlich.

Für die Installation dieses Pakets benötigen Sie die Java VM von Sun. Dabei handelt es sich um ein kostenloses Produkt, dass Sie unter http://java.sun.com herunterladen können.

Features

Suchindex erstellen

Um eine bessere Geschwindigkeit der Suche zu gewährleisten, erstellt die Suchmaschine ein Verzeichnis der durchsuchbaren Dokumente. Dieses Verzeichnis nennt sich "Suchindex". Sie haben die Wahl, diesen entweder: 1) offline auf Ihrem eigenen Rechner, oder 2) online in Yana erstellen lassen wollen.

Suchindex offline erstellen

Sie müssen die Seiten Ihrer Homepage nicht von Hand eintragen. Dem Paket liegt ein kleines Java-Tool bei, dass Ihnen diese Arbeit abnehmen kann.


Abbildung: graf. Oberfläche zum Erstellen eines Suchindex
Installation von Java

Um unter Windows herauszufinden, ob Java auf Ihrem System bereits installiert ist, genügt es meist nach der Datei "java.exe" zu suchen. Unter Windows, indem Sie im Startmenü auf "Suchen" > "Dateien und Ordner" gehen. Ist die Datei nicht vorhanden, müssen Sie Java noch installieren.

Diese Datei muss nach der Installation außerdem im Systempfad verknüpft sein. Dies können Sie prüfen, indem Sie in der Eingabeaufforderung "java" eingeben. Ihnen sollte nun eine Liste mit Optionen angezeigt werden. Falls nicht müssen Sie die Datei in den Systempfad eintragen.

Unter Windows-XP erledigen Sie dies in der Systemsteuerung unter "System" > "Erweitert" > "Umgebungsvariablen" > "Systemvariablen". Starten Sie den Rechner anschließend neu und versuchen Sie noch einmal "java" in der Eingabeaufforderung einzugeben. Sollte auch dies nicht von Erfolg gekrönt sein, bleibt Ihnen nichts anderes übrig, als Java neu zu installieren.

Bei älteren Versionen von Windows editieren Sie bitte die Datei "autoexec.bat". Fügen Sie den folgenden Eintrag hinzu (vorher bitte Kopie anlegen):
SET PATH="JAVA-Verzeichnis\bin\java.exe;%PATH%"

Sie können erfahren welche Java-Version Sie installiert haben, indem Sie "java -version" in der Eingabeaufforderung eingeben.

Indexer starten

Starten Sie die Datei start.bat mit Doppelklick. Das Programm hat eine grafische Oberfläche mit vielen bunten Icons und ist weitestgehend selbsterklärend. Es fragt die notwendigen Eingaben von Ihnen ab und erstellt anschließend per Klick einen Suchindex.

Alternativ: Verwendung der Kommandozeile

Tipp: Sie müssen die Kommandozeile NICHT benutzen. Es existiert eine grafische Nutzeroberfläche, welche Sie mit der Datei "start.bat" ausführen können. Sollte diese jedoch nicht funktionieren oder es Ihnen lieber ist, können Sie das Programm auch von der Kommandozeile aus starten.

Sie können die Indexierung über die DOS-Eingabeaufforderung, oder wahlweise mit Hilfe der Datei "suchIndexErstellen.bat" ausführen.

Diese Datei ist anfangs so eingestellt, dass das aktuelle Verzeichnis inklusive seiner Unterverzeichnisse durchsucht wird. Möchten Sie das ändern, müssen Sie diese Datei editieren oder das Programm von Hand über die Eingabeaufforderung starten. Ansonsten genügt es die Datei einfach per Doppelklick auszuführen.

In der Eingabeaufforderung:

java -classpath index.jar suchindexErstellen VERZEICHNIS VERFOLGEN METATAGS

VERZEICHNIS: ist das Verzeichnis, das durchsucht werden soll. Das aktuelle Verzeichnis ist zum Beispiel .\ das übergeordnete Verzeichnis ..\ heißt das Verzeichnis Homepage, geben Sie homepage\ an usw.
Bitte verwenden Sie lediglich relative Pfadangaben (also nicht C:\\...) sonst werden die Dateien mit Ihrer Festplatte verknüpft.
VERFOLGEN: gibt an, ob die in diesem Verzeichnis enthaltenen Unterverzeichnisse ebenfalls durchsucht werden sollen oder nicht. Geben Sie true an falls das geschehen soll oder false falls nicht.
METATAGS: gibt an, ob die in den Meta-Tags enthaltenen Keywords ebenfalls gespeichert werden sollen oder nicht. Geben Sie true an, falls Sie dies möchten, oder false falls nicht.

  Beispiele:

1) Wenn sich Ihre Homepage in "C:\Homepage" befindet und die Suchmaschine liegt in "C:\Homepage\suchmaschine" müssen die Java-Dateien in "C:\Homepage\suchmaschine" kopiert werden. Von hier muss auch der Aufruf erfolgen (auf der Kommandozeile):

java -classpath index.jar suchindexErstellen ..\ true true

2) Angenommen Ihre Homepage befindet sich in "C:\Homepage", Ihre Suchmaschine befindet sich wieder im Verzeichnis "C:\Homepage\suchmaschine" und Sie möchten aber nur das Verzeichnis "C:\Homepage\test" ohne seine Unterverzeichnisse durchsuchen. Dann geben Sie folgendes ein:

java -classpath index.jar suchindexErstellen ..\test\ false true

3) Ihre Homepage befindet sich (wieder) in "C:\Homepage", Ihre Suchmaschine befindet sich dieses Mal im gleichen Verzeichnis und Sie möchten nur das Verzeichnis "C:\Homepage\test" und seine Unterverzeichnisse - so lautet die Eingabe wie folgt:

java -classpath index.jar suchindexErstellen .\test\ true true

Startdatei:

Öffnen Sie zunächst die Datei suchIndexErstellen.bat mit einem normalen Texteditor (zum Beispiel Notepad). Hier finden Sie genau den gleichen Dateiaufruf wie oben inklusive der Beschreibung. Ändern Sie die Einstellungen Ihren Wünschen entsprechend, speichern und starten Sie die Datei.

Verwendung des Administrationsmenüs zum Upload des Suchindex
  1. Öffnen Sie das "Administrationsmenü".
  2. Stellen Sie sicher, dass das Setup-Plugin der Suchmaschine und die Suchmaschine selbst aktiviert sind.
  3. Rufen Sie im Optionsmenü das Menü "Suchmaschine Setup" auf.
  4. Klicken Sie im Menü "offline erstellten Suchindex auf Server kopieren" auf die Schaltfläche "Durchsuchen" um die lokal auf Ihrem Rechner gespeicherten Suchdateien auszuwählen
  5. Klicken Sie auf "OK" um den Upload durchzuführen

Abbildung: Formular im Administrationsmenü zum Upload des Suchindex

Suchindex online erstellen

  1. Öffnen Sie das "Administrationsmenü".
  2. Stellen Sie sicher, dass das Setup-Plugin der Suchmaschine und die Suchmaschine selbst aktiviert sind.
  3. Rufen Sie im Optionsmenü das Menü "Suchmaschine Setup" auf.
  4. Scrollen Sie zum Abschnitt "Suchindex online erstellen".
  5. Falls noch nicht geschehen, geben Sie den Namen des Quellverzeichnisses ein, welches Sie durchsuchen wollen.
  6. Klicken Sie auf "OK" um den Aufbau des Index zu starten.

Abbildung: Administrationsmenü zum Erstellen eines Suchindex

Häufig gestellte Fragen

Welche Informationen werden gespeichert?

Die Datenbank enthält alle in einem Dokument gefundenen Begriffe, "Keywords" und den Titel der Seite.
Die Suche beschränkt sich auf HTML-Dokumente (*.htm, *.html, *.xml, *.shtml). Gespeichert werden neben den gefundenen Suchbegriffen die URL der Seite und die ersten 80 Zeichen als Beschreibung.

Nicht durchsucht werden außerdem alle Verzeichnisse, deren Name mit einem Unterstrich: "_" beginnt. Der Grund ist, dass einige Homepageprogramme (wie z.Bsp. Frontpage) diese Schreibweise nutzen um Systemverzeichnisse zu markieren, die natürlich nicht durchsucht werden sollen.

Einige Dokumente haben sich geändert. Was muss ich tun damit die neuen Dateien gefunden werden?

Mit der Datei " suchIndexErstellen.bat " oder " start.bat " einen neuen Suchindex der Homepage erstellen und ins Netz laden. Dabei müssen die alten Dateien " keywords.dat " und " documents.dat " ersetzt werden. Falls vorhanden sollten Sie den Cache der Suchmaschine leeren indem Sie im Verzeichnis " cache/ " die Datei(en) " *.cache " löschen.

Ich habe einen neuen Suchindex erstellt aber es werden immer noch die alten Ergebnisse angezeigt.

Das kann passieren, wenn sich noch alte Daten im Cache der Suchmaschine befinden. Löschen Sie dazu im Verzeichnis " cache/ " alle Dateien mit der Endung " *.cache " und versuchen Sie es erneut.

Es wird nichts, bzw. 0 Treffer angezeigt.

Das Anzeigen der Trefferliste erledigt ein JavaScript. Das macht die Suchmaschine extrem schnell und entlastet den Server, weil beim Blättern durch die Suchergebnisse keine Daten vom Server nachgeladen werden müssen. Allerdings: muss dazu JavaScript in ihrem Browser aktiviert sein. Wenn die Seite leer bleibt prüfen Sie bitte ob JavaScript deaktiviert ist oder durch eine Firewall blockiert wird.

Was ist der Unterschied zwischen "start.bat", "suchIndexErstellen.bat" und "searchIndex.bat"?

Im Verzeichnis "tools" liegen 3 Dateien "start.bat", "suchIndexErstellen.bat" und "searchIndex.bat". Alle tun exakt das gleiche. Nur, dass die Datei "start.bat" eine grafische Oberfläche aufruft, die alle Daten über ein Menü abfragt. Die anderen beiden starten das Programm direkt von der Kommandozeile aus. Dort müssen Sie die Parameter von Hand direkt in der Datei ändern. Dabei zeigt "searchIndex.bat" die Beschreibung der Parameter in Englisch und "suchIndexErstellen.bat" die gleiche Beschreibung in deutscher Sprache an. Wählen Sie die Lösung, die Ihnen am besten gefällt.

Ich erhalte eine Fehlermeldung: "Fehler 500 Suchindex nicht gefunden".

Vermutlich haben Sie den Suchindex noch nicht erstellt oder die Dateien im falschen Verzeichnis abgelegt. Wie Sie einen Suchindex erstellen können Sie im Abschnitt "Suchindex erstellen" lesen.

Ich erhalte beim Suchen eine Fehlermeldung: "Fehler 404 Seite nicht gefunden".

Vermutlich haben Sie vergessen einige wichtige Dateien, ins Internet zu übertragen. Bitte prüfen Sie ob diese Dateien vorhanden sind.

Ich erhalte beim Suchen eine Fehlermeldung: "Fehler 403 Zugriff verweigert".

Das kann passieren wenn nicht ausreichende Zugriffsrechte gesetzt sind. Prüfen Sie bitte mit ihrem FTP-Programm ob für die Ordner " cache/ " und " config/ ", sowie alle Unterverzeichnisse und Dateien ausreichende Zugriffsrechte (lesen UND schreiben) gesetzt sind. Sie erreichen dies unter UNIX zum Beispiel mit dem Befehl CHMOD 777. Eine detaillierte Erläuterung der Zugriffsrechte finden Sie in der Installationsanleitung im Abschnitt für Anfänger.

Ich habe versucht die Datei "start.bat" auszuführen, aber es hat nicht funktioniert.

Bitte prüfen Sie, ob Sie mindestens Version 1.4.2 der Java Virtual Machine installiert haben. Geben Sie dazu in der Eingabeaufforderung ein "java -version". Sollte Sie eine ältere Version haben, laden Sie sich aus dem Netz unter java.sun.com kostenlos eine aktuellere Version der Java Virtual Machine herunter. Oder versuchen Sie die Datei "suchIndexErstellen.bat" um das Programm von der Kommandozeile aus zu steuern. Das ist zwar nicht so bequem, dafür reicht dann allerdings schon Version 1.3 der Java Virtual Machine aus.

Plugin: RSS-to-HTML Factory

Allgemeines

Dieses Plugin lädt eine RSS Datei Ihrer Wahl und erzeugt eine HTML-Seite, die Sie nach Ihren Wünschen anpassen können. Dazu können Sie das Template im Verzeichnis "skins/default/rss/template.html" editieren.

Das Plugin ist ideal geeignet für Leute, die bereits einen RSS-Feed für ihre Homepage haben oder erstellen möchten und gleichzeitig (für Leute ohne RSS- Reader) eine Newsseite anbieten wollen. Mit diesem Plugin spart man sich die doppelte Führung von Newsseite und RSS-Feed. Anstatt neue Meldungen in HTML und XML separat zu schreiben, braucht man nur noch den Feed zu aktualisieren. Die HTML-Seite wird automatisch erzeugt.

Konfiguration

Sie können sich nun eine Testseite ansehen, indem sie index.php?action=get_news aufrufen

Wenn Sie einen eigenen RSS-Feed einbinden möchten, dann wählen Sie im Administrationsmenü aus der Spalte "Optionen" den Eintrag "RSS-to-HTML Setup".

Plugin: Software Development Kit (SDK)

Allgemeines

Das SDK unterstützt den Entwickler durch eine grafische Oberfläche. Die grafische Oberfläche führt dabei durch vier Schritte, in denen Aussehen, Verhalten und allgemeine Informationen zur Anwendung und zum Urheber bereitgestellt werden können.

Installation

Es wird dringend empfohlen, das SDK nur auf Webservern zu installieren, welche für den öffentlichen Zugriff gesperrt sind. Beispielsweise auf einer lokalen Arbeitsstation, welche nicht über Netzwerk erreichbar ist.

Stellen Sie sicher, dass das Programm Schreibrechte für die Verzeichnisse "plugins" und "config" besitzt.

Falls Sie eine Einführung in die Benutzung des SDK wünschen, finden Sie diese im Kapitel "Plugins und Anwendungen erstellen". Ein praktisches Anwendungsbeispiel finden Sie im Einführungstutorial, in Kapitel 3 "Erstellen eines neuen Plugins".

Anleitung für Entwickler

Bevor Sie beginnen...

  1. Bitte schalten Sie immer zuerst den Debug-Modus ein.
    1. Öffnen Sie die Datei "index.php".
    2. Ändern Sie diesen Text: 
      error_reporting(0);
      in folgenden Text: 
      error_reporting(E_ALL);
      ErrorUtility::setErrorReporting(YANA_ERROR_ON);
    3. Speichern und schliessen Sie die Datei.
    4. Bitte deaktivieren Sie den Debug-Modus, bevor Sie die Software auf einen öffentlichen Server laden.
  2. Stellen Sie sicher, dass Sie das Plugin "SDK" installiert und aktiviert haben.
  3. Bitte lesen Sie das Tutorial. 
  4. Beachten Sie die API-Dokumentation. 
  5. Code-Beispiele finden Sie im Kochbuch für Entwickler. 

Editoren für das Yana Framework

Allgemeines

Viele Editoren können die Arbeit mit dem Yana Framework erleichtern. Um Sie beim Übersetzen, Entwickeln neuer Plugins, oder Schreiben von Skins zu unterstützen, stehen Syntax-Highlighter und Code-Templates für verschiedene Editoren zur Verfügung.

Der folgende Abschnitt soll Ihnen Beispiele zeigen und demonstrieren, wie diese Werkzeuge Ihre Arbeit erleichtern können.

Einbindung in ConTEXT

Installation

Für das Editieren der Konfigurationsdateien, Templates und Plugins des Yana Framework stehen Syntax-Highlighter und Code-Templates für "ConTEXT" zur Verfügung. ConTEXT ist ein Editor für Programmierer. Sie finden ihn im Internet unter der Adresse http://context.cx. Das Programm ist kostenlos und bietet Unterstützung für weit mehr als 50 Programmiersprachen und Dateiformate. Darunter das komplette Yana Framework.

Zur Installation der Highlighter und Templates für das Yana Framework installieren Sie zuerst ConTEXT. Öffnen Sie anschließend das Installationsverzeichnis des Editors und kopieren Sie die "ConTEXT Highlighter Files" (*.chl) in das Verzeichnis "Highlighters" und die "ConTEXT Template Files" (*.ctpl) in das Verzeichnis "Template" (siehe Abbildung). Falls Sie ConTEXT noch geöffnet haben, starten Sie den Editor bitte neu.


Abbildung: ConTEXT Installationsverzeichnis

ConTEXT bietet die Möglichkeit, die Hilfe des Yana Framework aus dem Editor heraus zu nutzen. Um diese Einzubinden gehen Sie wie folgt vor:

1. Öffnen Sie das Menü "Einstellungen" > "Umgebungseinstellungen"


Abbildung: Umgebungseinstellungen öffnen

2. Wechseln Sie in das Menü "Verschiedenes" und wählen Sie aus der Liste den Eintrag "Yana Framework" beziehungsweise "Yana Framework Templates" aus.

3. Klicken Sie auf die Schaltfläche "bearbeiten".


Abbildung: Hilfedateien zuordnen

4. Wählen Sie den Dateityp "all files (*.*)" aus, durchsuchen Sie Ihre Festplatte nach der Datei "index.html" dieses Handbuchs und wählen Sie mit der Maus diese Datei aus.

5. Klicken Sie auf die Schaltfläche "Öffnen"


Abbildung: Datei "index.html" als Startseite auswählen

5. Speichern Sie die Änderung durch Klick auf "OK".

Die erforderlichen Dateien finden Sie auf den folgenden Webseiten:

Verwendung

1. Beispiel: ein Datenbankschema editieren

Öffnen Sie eine Konfigurationsdatei (zum Beispiel ein Datenbankschema aus dem Verzeichnis yana/config/db/) mit ConTEXT und wählen Sie aus der Liste der Highlighter den Eintrag "Yana Framework".


Abbildung: Bearbeiten eines Datenbankschemas mit ConTEXT

2. Beispiel: ein Template editieren

Öffnen Sie ein Template mit ConTEXT und wählen Sie aus der Liste der Highlighter den Eintrag "Yana Framework Templates".


Abbildung: Bearbeiten einer Templatedatei mit ConTEXT

3. Beispiel: Textbausteine verwenden

Zum Einfügen von Code-Templates verwenden Sie die Tastenkombination <CTRL> + <j>, oder wählen Sie aus dem Menü "Format" den Eintrag "Textbaustein einfügen". Ein Auswahlmenü wird angezeigt. Dieses besteht aus zwei Teilen: Links sehen Sie ein Tastenkürzel und rechts eine Beschreibung. Wählen Sie mit der Maus oder den Pfeiltasten einen Baustein aus und drücken Sie <ENTER> zum Einfügen.

Sie können die Auswahl einzuschränken, indem Sie die Anfangsbuchstaben eines Bausteins eingeben. Wenn nur 1 passender Baustein zur Verfügung steht, wird dieser automatisch eingefügt und das Auswahlmenü wird nicht angezeigt.

Zum Beispiel: schnelles Erstellen eines Datenbankschemas.

  1. Öffnen Sie in ConTEXT eine neue Datei
  2. Wählen Sie den Highlighter "Yana Framework" aus
  3. Geben Sie ein "db" und drücken Sie <CTRL> + <j> um den Dateirumpf zu erzeugen
  4. Geben Sie ein "tbl" und drücken Sie <CTRL> + <j> um eine neue Tabelle zu erstellen
  5. Geben Sie als den Namen der Tabelle ein (beim schließenden Tag wiederholen)
  6. Im Abschnitt "Primary_Key" geben Sie "id" als Namen des Primärschlüssels an
  7. Wechseln Sie in den Abschnitt "CONTENT", geben Sie "id" ein und drücken Sie erneut <CTRL> + <j> um automatisch einen Primärschlüssel zu erzeugen
  8. Fügen Sie hinter der Spalte "id" auf einer neuen Zeile den Text "string" ein und drücken Sie <CTRL> + <j> um eine Spalte vom Typ "string" zu erzeugen
  9. Benennen Sie die Spalte (beim schließenden Tag wiederholen)
  10. Im Abschnitt "Description" können Sie den Inhalt der Spalte beschreiben

Das Ergebnis demonstriert die folgende Abbildung.


Abbildung: Erstellen einer neuen Tabelle mit wenigen Handgriffen

Weitere Abkürzungen können Sie der Auswahlliste entnehmen.

Einbindung in PSPad

Installation

Für das Editieren der Konfigurationsdateien, Templates und Plugins des Yana Framework stehen Syntax-Highlighter und Code-Templates für "PSPad" zur Verfügung. PSPad ist ein Texteditor für Webentwickler. Sie finden ihn im Internet unter der Adresse http://www.pspad.com. Das Programm ist als Freeware kostenlos erhältlich.

PSPad kann auch ohne Installation von einem USB-Stick gestartet werden.

Zur Installation der Highlighter und Templates für das Yana Framework installieren Sie zuerst PSPad. Öffnen Sie anschließend das Installationsverzeichnis des Editors und kopieren Sie die "Highlighter Files" (*.ini) in das Verzeichnis "Syntax" und die "Template Files" (*.def) in das Verzeichnis "Context" (siehe Abbildung). Falls Sie PSPad noch geöffnet haben, starten Sie den Editor bitte neu.


Abbildung: PSPad Installationsverzeichnis

Um die Installation abzuschließen, müssen Sie die neuen Dateien in PSPad noch aktivieren.

  1. Öffnen Sie dazu in PSPad das Menü "Settings" > "Highlighter Settings".
  2. Klicken Sie auf einen freien Slot (erkennbar durch den Text "not assigned")
  3. Wählen Sie das Menü "Specification" (siehe Abbildung)
  4. Wählen Sie aus dem Menü "User Highlighters" den Eintrag "Yana Framework" beziehungsweise "Yana Framework Templates"
  5. Sie aktivieren den Highlighter durch das Anklicken des Kästchens neben dem Namen
  6. Klicken Sie auf "OK"


Abbildung: Aktivieren der Highlighter

Die erforderlichen Dateien finden Sie auf den folgenden Webseiten:

Verwendung

1. Beispiel: ein Plugin editieren

Öffnen Sie eine Plugin-Definitionsdatei (plugins/*.config) mit PSPad.

Um den Highlighter auszuwählen, klicken Sie auf die Schaltfläche "Change document syntax highlight" (siehe Abbildung).


Abbildung: eine Konfigurationsdatei des Yana Frameworks in PSPad, rechts mit aktivem Code-Browser

Wählen Sie den Eintrag "Yana Framework" beziehungsweise "Yana Framework Templates" und klicken Sie auf "OK".


Abbildung: Syntax Highlighter auswählen

2. Beispiel: Textbausteine (Clips) verwenden

Ebenso wie ConTEXT kennt PSPad Textbausteine. Diese werden in PSPad "Clips" genannt und sind über das Tastenkürzel <CTRL> + <SPACE> erreichbar.

Die Handhabung ist identisch zu ConTEXT. Ein Auswahlmenü wird angezeigt. Dieses besteht aus zwei Teilen: Links sehen Sie ein Tastenkürzel und rechts eine Beschreibung. Wählen Sie mit der Maus oder den Pfeiltasten einen Baustein aus und drücken Sie <ENTER> zum Einfügen.

Sie können die Auswahl einzuschränken, indem Sie die Anfangsbuchstaben eines Bausteins eingeben.


Abbildung: Verwendung von "Clips" in PSPad

Templates und Skins erstellen

HTML-Vorlagen editieren

Dieses Programm verwendet Musterseiten, sogenannte "Templates". Was auch immer Sie auf diesen Seiten ändern, ändert auch das Aussehen und Verhalten der Anwendung. Diese Dateien befinden sich im Skinverzeichnis. Sie können diese Dateien so wie normale HTML-Seiten in Ihrem Webeditor laden und ändern. Zum Ändern der Dateien sind keine HTML-Kenntnisse notwendig, bei größeren Änderungen sind diese allerdings vorteilhaft.

In jedem Fall sollten Sie sich Kopien der Originaldateien anlegen, bevor Sie Änderungen vornehmen.

Schritt-für-Schritt Anleitung

  1. Im Basisverzeichnis Ihrer Anwendung finden Sie ein Verzeichnis mit dem Namen "skins/" in diesem Verzeichnis finden Sie alle derzeit installierten Skins.
  2. Um einen neuen Skin anzulegen kopieren Sie zunächst den Inhalt des Verzeichnisses "default/" inklusive seiner Unterverzeichnisse in ein neues Verzeichnis mit dem Namen Ihres Skins. Zum Beispiel "skins/meinskin/".
  3. Öffnen Sie die Datei "index.html" in einem Webeditor Ihrer Wahl. Sie können dazu auch Notepad bzw. unter Unix/Linux Emacs verwenden.
  4. Passen Sie Datei Ihren Wünschen an und speichern Sie Ihre Änderungen ab.
  5. Abschließend müssen Sie eine Konfigurationsdatei für Ihren Skin erstellen. Diese Datei enthält den Namen Ihres Skins, eine Beschreibung zum Autor. Sie können dazu die Datei "skins/default.config" als Vorlage verwenden. Kopieren Sie diese Datei unter einem neuen Namen. Zum Beispiel "skins/meinskin.config".
  6. Diese Skindatei können Sie mit einem beliebigen Texteditor editieren. Öffnen Sie die Datei, ändern Sie die Angaben so, wie gewünscht. Achten Sie darauf, dass die Dateipfade korrekt sind. Speichern Sie anschließend Ihre Änderungen.

Tutorials zum Erstellen eigener Templates finden Sie auf der Smarty-Homepage unter: http://smarty.net

Templates und Skins konfigurieren

Wenn Sie nicht nur ein bereits existierendes Template editieren, sondern ein neues - oder vielleicht sogar einen neuen Skin - erstellen wollen, dann genügt es nicht, die Template-Dateien zu editieren. Sondern Sie müssen auch die Konfiguration der Templates und Skins verstehen und anwenden.

Dies ist jedoch sehr einfach und erschöpft sich in zwei Konfigurationsdateien. Eine davon für Ihre neuen Templates und die andere für Ihren neuen Skin.

Konfiguration von Skins

Im Folgenden ein einfaches Beispiel.

<SKIN_INFO>
    <NAME>mein Skin</NAME>
    <DESCRIPTION>das ist eine Beschreibung meines Skins</DESCRIPTION>
    <AUTHOR>mein Name</AUTHOR>
    <CONTACT>meine Webseite</CONTACT>
    <LOGO>%SKINDIR%mein_skin/data/preview.gif</LOGO>
    <DIRECTORY>mein_skin/</DIRECTORY>
</SKIN_INFO>

Die Syntax ist weitgehend selbsterklärend. Die Felder "Name", "Description" (Beschreibung), "Author" (Autor) und "Contact" (Kontakt) sind Freitext. Für das Feld "Name" können Sie sich einen beliebigen Namen ausdenken, der Ihren Skin beschreibt. Ebenso beliebig ist das Feld "Description" (Beschreibung). Achten Sie darauf, dass als Whitespace nur Leerzeichen erlaubt sind. Sie können einen Zeilenumbruch bei Bedarf einfügen, indem Sie den Text "[br]" verwenden. Das Feld "Author" (Autor) sollte Ihren Namen enthalten und das Feld "Contact" (Kontakt) sinnvollerweise eine Mail- oder Internetadresse, über welche man Sie erreichen und/oder Updates downloaden kann.

Das Feld "Logo" gibt eine Vorschaugrafik an. Der Platzhalter %SKINDIR% bezieht sich auf das Verzeichnis, in welchem die Skins gespeichert sind und sollte stets angegeben werden. Die Grafik sollte vorzugsweise im GIF-, PNG- oder JPEG-Format gespeichert sein und etwa 300x300 Pixel groß sein.

Das Feld "Directory" muss stets angegeben werden. Es gibt an in welchem Verzeichnis der Skin gespeichert ist.

Konfiguration von Templates

Im Folgenden ein einfaches Beispiel.

<MY_TEMPLATE>
    <FILE>template.html</FILE>
    <STYLE>
        <0>style/default.css</0>
        <1>foo1/foo2.css</1>
        <MEIN_CSS>foo3/foo4.css</MEIN_CSS>
    </STYLE>
    <SCRIPT>
        <0>foo5/foo6.js</0>
        <MEIN_SCRIPT>foo7/foo8.js</MEIN_SCRIPT>
    </SCRIPT>
    <LANGUAGE>
        <0>guestbook</0>
        <1>admin</1>
    </LANGUAGE>
</MY_TEMPLATE>

Beachten Sie, dass "MY_TEMPLATE" als Identifier fungiert, welcher das Template identifiziert. Sie können diese Id in den Konfigurationsdateien Ihrer Plugins verwenden, um auf das Template zu verweisen. Der Text kann beliebig gewählt werden. Achten Sie jedoch darauf, dass die Id keine Sonderzeichen oder Leerzeichen enthält, mit einem Buchstaben beginnt und über die gesamte Anwendung hinweg eindeutig ist. Groß- und Kleinschreibung spielt keine Rolle.

Es gibt 4 Felder: "File", "Style", "Script" und "Language". Das Feld "File" gibt den Dateinamen an. Die restlichen Felder sind optional und dienen der Automatisierung.

Das Feld "Language" enthält Verweise auf eine oder mehrere Dateien, welche die Sprachinformationen für dieses Template enthalten. Beispielsweise bezieht sich der Wert "guestbook" auf die Datei "languages/XX/guestbook.config", wobei der Text "XX" automatisch vom System durch die vom Nutzer gewählte Sprache ersetzt wird. Zum Beispiel "de" für Deutsch beziehungsweise "en" für Englisch.

Das Feld "Style" kann mehrere Verweise auf Stylesheets enthalten. Ebenso enthält das Feld "Script" einen oder mehrere Verweise auf JavaScript-Dateien. Die angegebenen Dateien werden jeweils automatisch eingebunden, wenn das Template aufgerufen wird.

Hinweis: Ist in einem Skin ein erforderliches Template nicht definiert oder sind Eigenschaften dieses Templates ("Styles", "Script", "Languages") nicht erneut erklärt, so fällt das Programm automatisch auf den "Default"-Skin zurück.

Dies geschieht wie folgt.

  1. Fehlt im Skin ein Template, werden die Default-Einstellungen komplett verwendet.
  2. Existiert das Template, aber beispielsweise "Style" ist nicht definiert, dann wird dieser mit der "Style"-Definition des gleichnamigen Templates im Default-Skin überschrieben. Für "Language" und "Script" gilt dies analog.
  3. Existiert das Template und die Eigenschaft ist definiert, dann werden die definierten Eigenschaften mit denen des Default-Skins zusammengeführt.
    Dabei geht das Programm wie folgt vor:
    • Alle numerischen Einträge werden stets angehängt. Zum Beispiel: die Einträge STYLE.0, STYLE.1 usw. aus dem Default-Skin werden übernommen und die Einträge STYLE.0, STYLE.1, STYLE.2 usw. aus dem neuen Skin werden an die Liste angehängt.
    • Konkret benannte Einträge, wie zum Beispiel STYLE.MEIN_CSS aus dem Default-Skin, werden durch gleichnamige Einträge im neuen Skin ersetzt.

Dieses Verhalten mag zunächst unlogisch erscheinen, hat jedoch einen durchaus einen tieferen Sinn. Es erlaubt einzelne Stylesheets oder Scripts in einem neu erstellten Skin ganz gezielt auszutauschen. Gleichzeitig gestattet es aber auch einzelne Stylesheets oder Scripts von diesem Mechanismus auszuschließen. Beide Variante kommen vor und haben ihre Einsatzgebiete.

Ein weiteres Beispiel zur Illustration dieses Verhaltens. Die folgende Definition tauscht für das Template "MY_TEMPLATE" nur die CSS-Datei "MEIN_CSS" aus dem Default-Skin durch eine andere aus. Alle anderen Einstellungen bleiben unverändert.

<MY_TEMPLATE>
    <STYLE>
        <MEIN_CSS>foo/bar.css</MEIN_CSS>
    </STYLE>
</MY_TEMPLATE>

Wie Sie in diesem Beispiel sehen, wird keine neue HTML-Vorlage festgelegt, sondern es wird wieder die Vorlage des Default-Skin verwendet. Das heißt: es ist nicht erforderlich die HTML-Vorlage aus dem Default-Skin in den neuen Skin zu kopieren, oder zu editieren um ein neues Layout zu erzeugen. Dies vermeidet unnötige Redundanz und erleichtert Ihnen die Pflege Ihres HTML-Codes.

Liste der wichtigsten erlaubten Platzhalter

* "erforderlich" meint in diesem Fall "ungleich NULL"

Platzhalter Typ erforderlich * Defaultwert Herkunft Beschreibung
PHP_SELF String ja - PHP Name der ausgeführten Skriptdatei.
REMOTE_ADDR String ja - PHP Die IP-Adresse des Clients.
SETTINGS.WEBSITE_URL String nein - aufrufende URL komplette URL des Skriptes (inkl. http://...)
REQUEST_URI String nein - aufrufende URL aufgerufener Pfad des Skriptes, inklusive Parameter (/yana/index.php?...)
QUERY_STRING String nein - aufrufende URL an das Skripte übergebene Parameterliste
ID String ja default GET/POST ID-Code des gerade aktiven Profils.
ACTION String nein <empty> GET/POST Name der Aktion welche gerade ausgeführt wird bzw. welche ausgeführt werden soll.
TARGET String nein <empty> GET/POST Ziel der Aktion welche gerade ausgeführt wird bzw. welche ausgeführt werden soll. (bspw. die ID eines Datensatzes)
SESSION_NAME, SESSION_ID String nein <empty> GET/POST Name und ID-Code der gerade laufenden Session (sollten bei allen internen Links angegeben werden)
PAGE integer nein 0 GET/POST Die Nummer des Datensatzes, ab welchem mit der Anzeige begonnen werden soll. (falls erforderlich)
ATIME string ja - Dateiattribut Fügt Datum und Zeit des letzten Zugriffs auf das HTML-Template an dieser Stelle ein:
[%$ATIME|date%]
MTIME string ja - Dateiattribut Fügt an dieser Stelle das Datum ein, an welchem das HTML-Template zuletzt geändert worden ist:
[%$MTIME|date%]
CTIME string ja - Dateiattribut Fügt an dieser Stelle das Datum ein, an welchem das HTML-Template erstellt worden ist:
[%$CTIME|date%]
LANGUAGE Array ja - Sprachdatei(en) Array, welches alle Textstrings der gerade ausgewählten Übersetzung enthält.
PROFILE Array ja - Profildatei Array, welches alle Einstellungen des gerade aktiven Profils enthält.
Im Folgenden einige Beispiele. Beachten Sie, dass alle hier genannten Felder auch einen NULL-Wert enthalten dürfen.
PROFILE.BGCOLOR,
PROFILE.BGIMAGE
String nein - Profildatei Hintergrundfarbe und Hintergrundbild der Webseite
PROFILE.PFONT,
PROFILE.PSIZE,
PROFILE.PCOLOR
String nein - Profildatei Schriftart, Schriftgröße, Schriftfarbe für Standardabsätze (P-Tags)
PROFILE.HFONT,
PROFILE.HSIZE,
PROFILE.HCOLOR
String nein - Profildatei Schriftart, Schriftgröße, Schriftfarbe für Überschriften (H1-,H2-,H3-Tags)
SKIN_INFO Array nein - Skindatei Informationen zum gewählten Skin
LANGUAGE_INFO Array nein - Sprachdatei Informationen zur gewählten Sprache
LANGUAGE Array nein - Sprachdatei(en) Übersetzungen (Texte)
SETTINGS.WEBSITE_URL String nein - Sprachdatei(en) komplette URL des Skriptes (inkl. http://...)

Referenzhandbuch für Template-Engine

Allgemeines

Dieses Framework verwendet die "Smarty Template-Engine". Diese Engine besitzt Ihre eigene Dokumentation, welche kostenlos unter der Adresse http://smarty.net/docs.php zum Download bereit steht.

Es ist Ihnen gestattet, die Engine durch selbst geschriebene Funktionen zu erweitern. Auf diese Weise können Sie die Syntax der verwendeten Templates quasi beliebig erweitern. Sie finden die Engine im Verzeichnis "engine/". Eine Anleitung dazu finden Sie im Referenzhandbuch der Engine. Änderungen an der Engine sind jedoch nur Experten zu empfehlen.

Hinweis zu Lizenzen: Bevor Sie Änderungen vornehmen, beachten Sie bitte die Lizenzhinweise.

Abweichungen der Syntax

Die Syntax der verwendeten Version der "Smarty Template-Engine" weicht in einigen Punkten vom Referenzhandbuch ab. Der folgende Abschnitt beschreibt diese geänderte Syntax.

Kennzeichnung von Token

Anders als in der Originalversion von Smarty verwendet diese Version nicht die Zeichen '{' und '}' als öffnende und schließende Tags für die Auszeichnung von Smarty-Codes, sondern die unverfänglicheren Strings: '[%' und '%]'. Also beispielsweise NICHT "{$variable}", sondern "[%$variable%]". Der Grund ist, dass die ursprünglichen Zeichen in den meisten HTML-Dokumenten zu häufig im Fließtext bzw. in Skripten oder Stylesheets auftauchen, was zu Problemen bei der Abarbeitung der Templates führen kann. Daher wurden die Tags vorsorglich auf diese unverfänglichere Variante geändert. (Dieses Vorgehen wird zudem auch im Handbuch der Engine für solche Fälle empfohlen.)

Anders als in der Originalversion erlaubt diese Version auch den Einsatz einer verkürzten Syntax für das Einsetzen einfacher Variablen. Statt der etwas umständlicheren Schreibweise "[%$VARIABLE%]" ist in dieser Version auch folgende Schreibweise gestattet: "%VARIABLE%". Dies betrifft allerdings ausschließlich Variablen. Auf alle anderen Smarty-Codes ist dies NICHT anwendbar.

Namenskonventionen

Weil Smarty zwischen Groß- und Kleinschreibung unterscheidet wurde zur Vereinfachung festgelegt, dass Variablennamen prinzipiell in Großbuchstaben benannt sein sollten. Während die Namen von Funktionen und anderen Codes ausschließlich Kleinbuchstaben enthalten sollten. Aus Gründen der Übersichtlichkeit ist dringend zu empfehlen, sich an diese Konvention zu halten.

Pfadangaben

In dieser Version können Verweise auf Dateien (Links, Grafiken, CSS, Skripte, etc.) als relative Pfadangaben gespeichert werden. Dateipfade werden beim Laden der Seite automatisch korrigiert. Es ist also nicht mehr erforderlich, ausschließlich absolute Dateipfade zu verwenden.

Konfiguration

Smarty läuft in dieser Version im sicheren Modus (security=true). Das Einbetten von PHP-Codes in Templates ist nicht gestattet. Außerdem sind folgende Funktionen deaktiviert: include, include_php, php.

neue Funktionen

Hinweis: Das folgende Kapitel beschreibt zusätzliche Funktionen, welche Ihnen im Yana Framework zur Verfügung stehen und nicht zur Grundfunktionalität der Smarty Template Engine gehören. Die Grundfunktionen der Smarty Template Engine sind in der Dokumentation auf http://smarty.net/docs.php beschrieben.

captcha

[%captcha [ id="<string>" ] %]

Attribut Typ erforderlich Defaultwert Beschreibung
id string nein - Wert für das Attribut "id" des Tags "input"

Die Funktion "captcha" wird verwendet, um eine Grafik anzuzeigen, welches Text enthält, den der Besucher lesen und in das daneben eingeblendete Eingabefeld eingeben muss. Dies ist eine allgemein gebräuchliche Variante zum Schutz vor Spam.

Der Parameter "id" ist optional. Er kann beispielsweise verwendet werden, wenn eine Beschreibung in einem "label" angezeigt werden soll.

1. Beispiel:

[%captcha%]


Abbildung: Darstellung im Browser

2. Beispiel, mit Parameter "id":

<label for="myCaptcha">Bitte geben Sie den Text auf dem Bild ein</label>
[%captcha id="myCaptcha"%]

Weitere Hinweise finden Sie auch im Kochbuch für Entwickler, Kapitel "Verwenden eines CAPTCHA".

create

[%create template="<string>" file="<string>" table="<string>" [ where="<string>" ] [ desc="<boolean>" ] [ sort="<string>" ] [ page="<integer>" ] [ entries="<integer>" ] [ titles="<boolean>" ] [ on_new="<string>" ] [ on_edit="<string>" ] [ on_delete="<string>" ] [ on_search="<string>" ] %]

Attribut Typ erforderlich Defaultwert Beschreibung
template string ja - Name des Templates, welches zum Generieren der GUI verwendet werden soll. Erlaubte Werte sind:
view_seperated, view_details, view, new, edit, search
file string ja - Pfad der Strukturdatei welche verwendet werden soll.
table string ja - Name der Tabelle, welche verwendet werden soll
show string nein - durch Kommata getrennte Liste von Spalten der Tabelle, welche in der Ausgabe angezeigt werden sollen (Kleinschreibung verwenden)
hide string nein - durch Kommata getrennte Liste von Spalten der Tabelle, welche in der Ausgabe NICHT angezeigt werden sollen (Kleinschreibung verwenden)
where string nein <empty> wird verwendet um die WHERE-Klausel für die SQL-Anfrage zu generieren.
Syntax: <FELDNAME1>=<WERT1>[,<FELDNAME2>=<WERT2>[,...]]
desc boolean nein false Gibt an, ob die Einträge aufsteigend (false) oder absteigend (true) sortiert werden sollen.
sort string nein <primary key> Name der Spalte, nach welcher die Einträge sortiert werden sollen
page integer nein 0 Nummer des ersten Eintrags der angezeigt werden soll
entries integer nein 5 Anzahl der insgesamt anzuzeigenden Einträge
titles boolean nein true Legt fest, ob Attributnamen angezeigt werden sollen oder nicht.
on_new string nein - Name der Aktion welche ausgelöst werden soll wenn ein neuer Eintrag gespeichert werden soll
on_edit string nein - Name der Aktion welche ausgelöst werden soll wenn geänderte Einträge gespeichert werden sollen
on_delete string nein - Name der Aktion welche ausgelöst werden soll wenn ausgewählte Einträge gelöscht werden sollen
on_search string nein - Name der Aktion welche ausgelöst werden soll um eine Suchanfrage zu bearbeiten und die Trefferliste zu erzeugen
on_download string nein download_file Name der Aktion welche ausgelöst werden soll wenn der Nutzer eine Datei oder ein Bild herunterladen möchte
layout int nein 0 Sollte ein Formular mehrere Darstellungsmöglichkeiten bieten, so können Sie mit diesem Parameter zwischen diesen wechseln.

Die Funktion "create" generiert automatisch eine GUI für eine gewählte Datenbank. Voraussetzung ist das Vorhandensein einer gültigen Strukturdatei, welche die Datenbank beschreibt.

Beispiel:

[%create template="edit" file="database.config" table="bookstore"%]

Ein Beispiel für eine Funktion, zum Download einer Datei (Argument "on_download"):

<?php
function myDownload($ARGS)
{
   if ($source = DbBlob::getFileId() === false) {
       return false;
   }
   // Download einer Datei:
   if (preg_match('/\.gz$/', $source)) {
       $dbBlob = new DbBlob($source);
       $dbBlob->read();
       header('Content-Disposition: attachment; filename=' . $dbBlob->getPath());
       header('Content-Length: ' . $dbBlob->getFilesize());
       header('Content-type: ' . $dbBlob->getMimeType());
       print $dbBlob->get();
       // Download einer Grafik:
   } else {
       $image = new Image($source);
       $image->outputToScreen();
   }
   exit;
}
?>

Achtung! Diese Funktion prüft nicht automatisch, ob der Nutzer die ausgewählte Datei im Sinne der Semantik Ihres Programms herunterladen "darf". Dies ist leider auch gar nicht möglich, ohne die Kriterien zu kennen, welche Sie innerhalb Ihres Programms dafür anwenden. Daher bleibt es an dieser Stelle Ihnen überlassen zu verifizieren, dass der Benutzer die notwendige Berechtigung besitzt, um die gewünschte Datei einzusehen.

embeddedTags

[%embeddedTags [ show="<string>" ]  [ hide="<string>" ] %]

Attribut Typ erforderlich Defaultwert Beschreibung
show string nein * eine durch Kommata getrennte Liste der Tags,
die angezeigt werden sollen
hide string nein - eine durch Kommata getrennte Liste der Tags,
die ausgeblendet werden sollen

Die Funktion "embeddedTags" generiert automatisch eine Schaltflächen, mit denen der Gast Ihrer Webseite beim Schreiben eines neuen Eintrags Text formatieren kann (fett, kursiv, etc.).

Die Liste "show" kann verwendet werden, um Tags festzulegen, welche angezeigt werden sollen und die Liste "hide" kann man benutzen, wenn Sie möchten, dass ganz bestimmte Tags nicht dargestellt werden.

Sie können in der Liste "show" mit dem Zeichen "-" Zeilenumbrüche und mit dem Zeichen "|" Trennstriche in die Ausgabe einfügen.

Beispiel:

<textarea id="text"></textarea>


Abbildung: Darstellung der Tag-Leiste (mit allen Tags)

<!-- Alle Tags einblenden -->
[%embeddedTags%]
<!-- Die Tags "u", "i" und "b" einblenden -->
[%embeddedTags show="b,u,i"%]
<!-- Alle Tags außer "url" und "mail" einblenden -->
[%embeddedTags hide="url,mail"%]
<!-- Die Tags "u","i","b", einen Trennstrich und dann den Tag "url" anzeigen -->
[%embeddedTags show="u,i,b,|,url"%]

import

[%import [preparser="true"] file="<string>"%]

[%import [preparser="true"] id="<string>"%]

Attribut Typ erforderlich Defaultwert Beschreibung
file string ja - Pfad der einzufügenden Datei
preparser boolean nein false bestimmt ob die Datei vor (true) oder während (false) des Parsens des Templates importiert werden soll

Oder alternativ mit folgenden Parametern:

Attribut Typ erforderlich Defaultwert Beschreibung
id string ja - Id des einzufügenden Templates
preparser boolean nein false bestimmt ob die Datei vor (true) oder während (false) des Parsens des Templates importiert werden soll

Die Funktion "import" ersetzt die verschiedenen ursprünglichen Funktionen zum Einfügen von Dateien durch eine einheitliche Funktion. Sie unterscheidet sich außerdem in der Art, wie die Dateien behandelt werden. Die Funktion "import" behandelt die zu importierende Datei wie ein eigenständiges Template. Dieses hat mehrere Vorteile: das eingefügte Template unterliegt bspw. den selben Sicherheitseinschränkungen wie das Basistemplate. Außerdem (und noch viel wichtiger:) sorgt dieses Vorgehen dafür, dass die Korrektur enthaltener Pfadangaben korrekt arbeiten kann.

Der Parameter "file" gibt den Namen der Datei an, welche importiert werden soll.

Alternativ kann der Parameter "id" verwendet werden, um statt den Pfad und Dateinamen fest im Template vorzugeben, die Id des Templates anzugeben. Das Framework bestimmt den zu der Id passenden Dateinamen zur Laufzeit automatisch. Dies hat den Vorteil, dass die Datei umbenannt oder in einen anderen Pfad verschoben werden kann, ohne dass die Verweise auf diese Datei in allen anderen Templates korrigiert werden müssen.

Anwendungsbeispiel: angenommen Sie haben ein Template "a.html" für den Skin "default" definiert und dieser importiert das Template "b.html". Nun möchten Sie einen neuen Skin anlegen. In diesem Skin wollen Sie den Inhalt der Datei "b.html" ändern, aber den Inhalt der Datei "a.html" unverändert lassen.
1. Fall: Falls Sie im Skin "default" das Template "b.html" über den Parameter "file" importiert haben, dann können Sie "b.html" in Ihrem neuen Skin nicht ändern, ohne den Pfad in "a.html" zu ändern. Das bedeutet, Sie müssten in Ihrem neuen Skin auch die Datei "a.html" anpassen.
2. Fall: Falls Sie im Skin "default" dem Template "b.html" eine Id (zum Beispiel "b") zugewiesen haben und das Template über den Parameter "id" importiert haben, dann können Sie in Ihrem neuen Skin die Id des Template "b" mit dem Pfad einer anderen Datei überschreiben, welche nur für diesen Skin verwendet wird. Dadurch müssen Sie den Pfad im Template "a.html" nicht ändern und können das Template unverändert lassen.
Hinweis: Das Zuweisen von Ids zu Dateien erledigen Sie über die Konfigurationsdateien (*.config) im Verzeichnis des jeweiligen Templates.

Das Flag "preparser" bestimmt, wann eine Datei importiert werden soll: BEVOR oder WÄHREND der Parser das Template abarbeitet. Wird es gesetzt, wird die Datei VOR dem eigentlichen Parsen eingefügt. Das Flag "preparser" sollte beispielsweise immer dann verwendet werden, wenn das importierte Template auf Variablen zugreifen muss, welche durch das Basistemplate gesetzt werden. Klassisches Beispiel sind Templates, welche innerhalb des Körpers von Schleifen importiert werden. ("foreach", "section") Diese benötigen das Flag "preparser", falls sie auf die Schleifenvariablen zugreifen können müssen. Alternativ können Sie der Anweisung "Import" eine Liste aller Variablen übergeben, auf welche Sie innerhalb des Templates zugreifen müssen.

Achtung! Wird der Parameter "preparser" verwendet, so wird das importierte Template nicht einzeln geparst, übersetzt und im Cache gespeichert, sondern in den Quellcode des Templates kopiert, welches die Import-Anweisung enthält. Es wird zur Laufzeit nicht geprüft, ob sich der Inhalt des importierten Templates seit dem letzten Aufruf geändert hat. Wenn Sie das importierte Template ändern, müssen Sie daher den Template-Cache explizit leeren, damit die Änderungen wirksam werden.

1. Beispiel, mit Parameter "file":

Datei "hello_world.html"
Hello World!

Datei "template.html"
<p>[%import file="hello_world.html"%]</p>

2. Beispiel, mit Parameter "id":

Datei "default.config"
<hello>
  <file>hello_world.html</file>
</hello>

Datei "template.html"
<p>[%import id="hello"%]</p>

3. Beispiel, zusätzliche Parameter:

Datei "hello_world.html"

[%if $foo%]
[%$bar%]
[%/if%]

Datei "template.html"
<p>[%import file="hello_world.html" foo=true bar="Hello World!"%]</p>

Ausgabe (in allen 3 Beispielen):

<p>Hello World!</p>

preview

[%preview [ width="<integer>" ] [ height="<integer>" ] %]

Attribut Typ erforderlich Defaultwert Beschreibung
width integer nein 380px Breite in Pixel
height integer nein 50px Höhe in Pixel

Die Funktion "preview" erzeugt ein Vorschaufenster auf einen Eintrag, welchen der Besucher geschrieben hat.

Im Text enthaltene Smilies und Tags werden dabei grafisch dargestellt. Dadurch hat der Besucher die Möglichkeit vor dem Abschicken des Formulars zu prüfen, wie sein Beitrag aussehen wird.

Beim Aufruf der Funktion werden automatisch die erforderlichen JavaScript-Dateien eingebunden. Außerdem wird eine Schaltfläche mit der Aufschrift "Vorschau" erstellt. (In der englischen Version lautet die Beschriftung "Preview".) Beim Anklicken wird oberhalb dieser Schaltfläche ein Fenster eingeblendet, welches die Vorschau zeigt.

Beispiel:

<textarea id="text"></textarea>
[%preview%]


Abbildung: Die Vorschau wird durch Anklicken der Schaltfläche
"Vorschau" über einen "AJAX HTTP-Request" vom Server geladen


Abbildung: Darstellung der Vorschau im Browser

Die Attribute "width" und "height" geben Breite und Höhe des Vorschaufensters an. Diese Werte werden als CSS-Anweisungen umgesetzt. Wenn Sie diese verwenden möchten, achten Sie daher bitte darauf, dass Sie eine Maßeinheit (zum Beispiel "px" für Pixel) angeben müssen. Prozentuale Angaben, wie "70%" sind ebenfalls erlaubt. Zahlen ohne Maßeinheit, wie "70" werden jedoch im Browser möglicherweise fehlerhaft dargestellt.

Die Angaben beziehen sich nicht auf die gesamte Größe des Vorschaufensters, sondern sinnigerweise auf den darin dargestellten Text. Die folgende Abbildung demonstriert dies:


Abbildung: Darstellung der Randbereiche

Der hier lila gefärbte Bereich ist der, dessen Größe über die Attribute "width" und "height" festgelegt wird. Der hellgrüne Bereich ist die Gesamtgröße des Feldes. Der Platz, welcher für die Überschrift benötigt wird, ist hellblau dargestellt. Der Rahmen ist hier violett angedeutet. Die Gesamtgröße des Fensters richtet sich also nach den Werten der Attribute "width" und "height", zuzüglich der Überschrift, des Rahmens (border) und des Randbereichs (margin) des Fensters.

printArray

[%printArray value="<array>" %]

Attribut Typ erforderlich Defaultwert Beschreibung
value array ja - ein Array, welches als String ausgegeben werden soll

Diese Funktion wandelt ein (eventuell mehrdimensionales) Array in einen String um und gibt diesen aus. Das Array wird im SML-Format dargestellt. Dies kann unter anderem für das Debugging von Templates interessant sein, um herauszufinden welchen Namen eine gesuchte Variable hat.

• Hinweis: Ab Version 2.9.3 des Yana Frameworks unterstützt diese Funktion Syntaxhervorhebung bei der Ausgabe.

Beispiel:

[%printArray value=$LANGUAGE%]


Abbildung: kurzer Auszug aus der Ausgabe

printUnorderedList

[%printUnorderedList value="<array>" [ keys_as_href="<bool>" ] [ layout="<int>" ] %]

Attribut Typ erforderlich Defaultwert Beschreibung
value array ja - ein Array, welches als Liste ausgegeben werden soll
keys_as_href bool nein false gibt an, ob Links erzeugt werden sollen
layout int nein 1 lässt Sie zwischen 3 alternativen Layouts (1, 2 und 3) für Ihr Menü wählen

Diese Funktion wandelt ein (eventuell mehrdimensionales) Array in eine unsortierte Liste im HTML-Format um und gibt diese aus. Es wird der Tag "ul" verwendet.

Man kann diese Funktion verwenden, um Baummenüs zu erzeugen. Wahlweise können in diesem Menü Links erzeugt werden. Dazu verwenden Sie bitte die URLs als Schlüssel des Arrays und die Beschriftung als Werte. Außerdem setzen Sie den Parameter "keys_as_href" auf "true".

1. Beispiel – ein Array als Baummenü darstellen:

[%printUnorderedList value=$LANGUAGE%]

 


Abbildung: kurzer Auszug aus der Ausgabe

 

2. Beispiel – ein Baummenü mit Links ausgeben:

<?php
$A = array(
    '1.html' => 'Link',
    'Menü 1' => array(
        '2_1.html' => '1. Eintrag',
        '2_2.html' => '2. Eintrag',
        'Menü 2' => array(
            '2_3_1.html' => '1. Eintrag',
            '2_3_2.html' => '2. Eintrag'
        ),
    ),
    'Menü 3' => array(
        '3_1.html' => '1. Eintrag',
        '3_2.html' => '2. Eintrag',
        '3_2.html' => '3. Eintrag'
    ),
);
$YANA->setVar('A', $A);
?>

[%printUnorderedList value=$A keys_as_href="true"%]

 


Abbildung: Darstellung als Baummenü mit Links

3. Beispiel – weitere Layouts:

[%printUnorderedList value=$A layout=2 keys_as_href="true"%]


Abbildung: Darstellung als vertikales Baummenü

[%printUnorderedList value=$A layout=3 keys_as_href="true"%]


Abbildung: Darstellung als horizontales Baummenü

Die Schlüssel werden fett gedruckt und die Werte kursiv - dies lässt sich jedoch per CSS ändern. Es werden folgende CSS-Klassen verwendet:

rss

[%rss [ image="<string>" ] %]

Attribut Typ erforderlich Defaultwert Beschreibung
image string nein - das Icon, auf welches der Besucher klicken kann um den RSS-Feed zu sehen.

Diese Funktion erzeugt Hyperlinks, zu den verfügbaren RSS-Feeds einer Webseite.

Das Argument "image" kann verwendet werden, um ein Icon auszuwählen. Klickt der Nutzer auf diesen Link, so wird die entsprechende Datei geöffnet. Die Liste der RSS-Feeds wird im Quellcode der Anwendung erzeugt. Siehe dazu auch das Kochbuch für Entwickler, Kapitel: "Sonstige Funktionen".

• Tipp: Auch wenn Sie die Hyperlinks nicht erzeugen, können Ihre Besucher die verfügbaren RSS-Feeds Ihrer Webseite trotzdem lesen, weil diese Links zusätzlich im Header der Datei zu finden sind. Diese Informationen kann der Browser des Besuchers, sofern er dazu in der Lage ist, verwenden, um Ihrem Besucher das Lesen der Feeds zu ermöglichen. Diese Variante ist für Ihre Gäste allerdings umständlicher und sollte daher vermieden werden.

Beispiel:

[%rss%]

RSS
Abbildung: Ausgabe der Funktion

Beispiel – einen Feed zur Ausgabe hinzufügen:

<?php
// Der Wert 'mein_rss' ist der Name der Funktion, welche den RSS-Feed ausgibt
RSS::publish('mein_rss');
?>

• Hinweis: In den mitgelieferten Skins werden die Hyperlinks auf vorhandene RSS-Feeds automatisch erzeugt, so dass Sie diese Funktion in der Regel nicht selbst benötigen, außer wenn Sie einen eigenen Skin schreiben. In diesem Fall sollten Sie die Hyperlinks in den Kopfbereich der Seite einbinden, wo diese für Besucher leicht zugänglich sind.

sizeOf

[%sizeOf value="<mixed>" [ assign="<string>" ] %]

Attribut Typ erforderlich Defaultwert Beschreibung
value mixed ja - skalarer Wert oder Array, dessen Länge bestimmt werden soll
assign string nein - Name der Template-Variable in welcher das Ergebnis zu speichern ist

Die Funktion "sizeOf" gibt die Länge eines Arrays oder Strings als Zahl zurück. Falls der Parameter "assign" angegeben wird, so wird der Rückgabewert in der Variable mit diesem Namen gespeichert und die Funktion liefert kein Ergebnis zurück.

Beispiel:

<td colspan="[%sizeOf value=$cols%]"> ... </td>

Beispiel mit "assign":

[%sizeOf value=$cols assign="foo"%] <td colspan="[%$foo%]"> ... </td>

smilies

[%smilies [ width="<integer>" ] %]

Attribut Typ erforderlich Defaultwert Beschreibung
width integer nein 1 Anzahl der Spalten der Tabelle

Die Funktion "smilies" generiert automatisch eine Tabelle aller verfügbaren Emoticons / Smilies, mit einem Link zum Einfügen in das angegebene Eingabefeld.

Beispiel:

<textarea id="text"></textarea>
[%smilies width="5"%]


Abbildung: Darstellung der Smilies (5 pro Zeile)

smlLoad

[%smlLoad file="<string>" [ section="string" ] [ scope="string" ] %]

Attribut Typ erforderlich Defaultwert Beschreibung
file string ja - Anzahl der Spalten der Tabelle
section string nein - ID eines Input- oder Textarea-Tags
scope string nein local gültige Werte: "local", "global", "parent", "template_vars"

Diese Funktion bietet die gleiche Schnittstelle wie die Smarty-Funktion "config_load". Allerdings arbeitet diese Funktion mit SML-Dateien mit den Dateiendungen "*.sml", "*.cfg" oder "*.config".

Anders als die herkömmlichen Konfigurationsdateien der Smarty-Engine, dürfen SML-Dateien mehrdimensionale Array-Definitionen enthalten.

Außerdem darf das Argument "scope" den Wert "template_vars" besitzen, welcher bewirkt, dass die Variablen der SML-Datei als Templatevariablen verwendet werden  - damit ist es möglich auf mehrdimensionale Arrays in gewohnter Weise zuzugreifen. Dieses Feature gibt es nur für smlLoad() und nicht für config_load().

Beispiel:

Im Verzeichnis "skins/.config" liegt die Datei "foo.sml". Sie hat folgenden Inhalt:

<TEST>
    <A>1</A>
    <B>
        <C>2</C>
    </B>
</TEST>

Im Template steht:

[%smlLoad file="foo.sml" section="TEST.B" scope="template_vars"%]
[%$C%]

Ausgabe: 2

[%smlLoad file="foo.sml" section="TEST.B"%]
[%#C#%]

Ausgabe: 2

[%smlLoad file="foo.sml" scope="template_vars"%]
[%$TEST.B.C%]

Ausgabe: 2

sml_load

Der Funktionsname "sml_load" ist ein Alias für die Funktion "smlLoad". Sie können beide Bezeichnungen alternativ verwenden.

Zur Beschreibung dieser Funktion.

varDump

[%varDump var="<mixed>" %]

• Hinweis: Diese Funktion dient ausschließlich dem Debugging. Sie steht nur zur Verfügung, wenn das Framework im Debugmodus betrieben wird. Ist dieser Modus deaktiviert, wird beim Versuch die Funktion aufzurufen ein Fehler erzeugt. Dies dient der Sicherheit Ihrer Anwendung.

Attribut Typ erforderlich Defaultwert Beschreibung
var mixed ja - Wert der ausgegeben werden soll

Die Funktion "varDump" gibt den Inhalt einer Variablen aus.

Beispiel:

[%varDump value=$INSTALLED_LANGUAGES%]

Ausgabe:

array ( 'de' => 1, 'en' => 1 )

neue Modifier

Hinweis: Das folgende Kapitel beschreibt zusätzliche Modifier, welche Ihnen im Yana Framework zur Verfügung stehen und nicht zur Grundfunktionalität der Smarty Template Engine gehören. Die Grundfunktionen der Smarty Template Engine sind in der Dokumentation auf http://smarty.net/docs.php beschrieben.

css

[%$foo|css%]

Erstellt eine Verknüpfung mit dem angegebenen Pfad einer CSS-Datei.

Beispiel:

[%"default.css"|css%]

wird umgesetzt zu:

<link rel="stylesheet" type="text/css" href="default.css">

date

[%$foo|date%]

Erzeugt aus einer Variable, welche einen UTC enthält, eine JavaScript-Anweisung, welche die passende Zeitangabe entsprechend der Zeitzone des Client-Browsers als Text ausgibt.

Beispiel:
Template wurde erzeugt am: [%$CTIME|date%]<br>
Template wurde zuletzt bearbeitet am: [%$MTIME|date%]<br>
Template wurde zuletzt aufgerufen am: [%$ATIME|date%]<br>

wird umgesetzt zu:

Template wurde erzeugt am: 1.12.2006
Template wurde zuletzt bearbeitet am: 19.1.2007
Template wurde zuletzt aufgerufen am: 21.1.2007

embeddedTags

[%$foo|embeddedTags%]

Ersetzt in einer Variablen vom Typ String Tags gemäß der für YANA vorgegebenen Syntax.

Beispiel:

$foo = "Text [b]Text[/b] Text"

wird umgesetzt zu:

Text <span style="font-weight: bold;">Text</span> Text

href

[%$foo|href%]

Generiert einen Link auf die Datei index.php inklusive aller erforderlichen Parameter. Der String $foo wird an das Ende des Search-Strings der URL angehängt. Um die URL werden automatisch doppelte Anführungszeichen (") erzeugt.

Beispiel:

<a href=[%"action=meinplugin_new_entry"|href%]>Neuer Eintrag</a>

wird umgesetzt zu:

<a href="index.php?sessid=foo&amp;id=beispiel&amp;action=meinplugin_new_entry">Neuer Eintrag</a>

smilies

[%$foo|smilies%]

Ersetzt in einer Variable vom Typ String enthaltene Codes durch die dazu passenden Icons.

Beispiel:

$foo = "Text :example: Text"

[%$foo|smilies%]

wird umgesetzt zu:

Text
<img border="0" hspace="2" src="common_files/smilies/example.gif">
Text

url

[%$foo|url%]

Generiert ebenso wie der Modifier "href" einen Link, allerdings als absoluten Pfad und ohne Anführungszeichen zu erzeugen.

Beispiel:

<meta http-equiv="Refresh" content="2; URL=[%"action=meinplugin_new_entry"|url%]">

wird umgesetzt zu:

<meta http-equiv="Refresh" content="2;
URL=http://.../index.php?sessid=foo&amp;id=beispiel&amp;action=meinplugin_new_entry">

Achtung!  Folgendes funktioniert nicht: <a href="[%"action=foo"|url%]">link</a>
Ergebnis: <a href="skins/default/http://.../index.php?...">link</a>

urlEncode

[%$foo|urlEncode%]

Kodiert einen Text so, dass er sicher als Parameter in einer URL verwendet werden kann. Dazu wird die PHP-Funktion urlencode() verwendet.

Beispiel:

<a href="?bar1=foo1&amp;bar2=[%$foo|urlEncode%]">

wird umgesetzt zu:

<a href="?bar1=foo1&amp;bar2=foo%20bar">

Plugins und Anwendungen erstellen

Allgemeines

Im Yana Framework werden alle Webanwendungen als "Plugins" bezeichnet. Komplexere Anwendungen können aus mehreren Subsystemen bestehen. Diese Subsysteme sind jeweils verschiedene Plugins, die Hand in Hand arbeiten. Einige dieser "Subsysteme" sind bereits vorbereitet implementiert und müssen lediglich verwendet werden.

Auf diese Weise bleiben dem Programmierer viele Arbeiten erspart. Sie müssen sich beispielsweise keine Sorgen um die Passwortabfrage machen. Es gibt bereits Plugins, welche das zuverlässig für Sie erledigen. Auch das Administrationsmenü müssen sie nicht neu schreiben, sondern es einfach nur verwenden. Falls eine Komponente nicht gefällt, kann sie ausgetauscht oder entfernt werden. Falls eine Funktion fehlt, kann sie hinzugefügt werden, ohne andere Plugins verändern zu müssen.

Das Schreiben eines neuen Plugins wird einfacher unter Verwendung des YANA-SDK. Dabei handelt es sich um einen Assistenten, welcher alle erforderlichen Informationen abfragt und dann vollautomatisch eine neue Anwendung für Sie erstellt. Diese müssen Sie lediglich noch Ihren Bedürfnissen anpassen.

Software Development Kit (YANA-SDK)

Das SDK unterstützt den Entwickler durch eine grafische Oberfläche. Die grafische Oberfläche führt dabei durch vier Schritte, in denen Aussehen, Verhalten und allgemeine Informationen zur Anwendung und zum Urheber bereitgestellt werden können.
Es wird dringend empfohlen, das SDK nur auf Webservern zu installieren, welche für den öffentlichen Zugriff gesperrt sind. Falls Sie eine Installationsanleitung benötigen, finden Sie diese im Kapitel "Software Development Kit / Installation".

Schritt 1: allgemeine Informationen

Formular 1

Vorbereitend müssen zunächst allgemeine Informationen gegeben werden. Siehe Abbildung oben.

Name der Software:
ein beliebiger Text.
Beschreibung:
ein beliebiger Text. HTML ist NICHT gestattet.
Grafik:
wählen Sie aus der Liste ein Icon, welches die Anwendung repräsentiert

Formular 2

Einige Informationen zu Ihrer Person:

Autor:
Ihr Name
Mailadresse:
Adresse für Rückfragen. Sie können das Feld frei lassen, falls Sie möchten.
Homepage für Updates:
eine gültige URL. Wenn Sie eine Webseite haben, auf der Sie Updates für diese Anwendung bereitstellen möchten, geben Sie hier die Adresse an.

Formular 3

Priorität der Ausführung:
Dieser Wert bestimmt, in welcher Reihenfolge Plugins ausgeführt werden. Sicherheitsrelevante Plugins (Passwortabfragen etc.) sollten eine höhere Priorität haben, dadurch werden sie ausgeführt, bevor andere Plugins an der Reihe sind. Andere Plugins (Log-Files etc.) sollten eine niedrigere Priorität haben.
Typ der Anwendung:
Gültige Werte für den Typ der Anwendung sind:
"default", "primary", "config", "read", "write",  "security".
  • die Mitglieder der Gruppe "security" werden immer ausgeführt und haben eine höhere Ausführungspriorität als alle anderen Plugins. Diese Gruppe dient für Plugins zur Nutzerauthentifizierung.
  • Die Gruppe "config" behandelt ausschließlich Ereignisse vom Typ "default", "security" oder "config". Sie ist gedacht für Plugins welche Funktionen zum Editieren von Konfigurationsdateien bereitstellen. Üblicherweise dienen diese Plugins als Erweiterungen anderer Plugins. Es besteht also eine Abhängigkeit. Diese Abhängigkeit kann unter anderem dadurch ausgedrückt werden, indem definiert wird, dass beide Plugins zum gleichen Paket gehören.
  • Die Gruppe "write" behandelt Ereignisse vom Typ "write", "security" oder "default". Sie ist gedacht für Plugins, welche ausschließlich Schreibzugriffe auf dem Dateisystem oder einer Datenbank durchführen. Diese Gruppe wird erfahrungsgemäß in der Praxis eher selten verwendet. Sie ist aus Gründen der Vollständigkeit hier erwähnt.
  • Die Gruppe "read" behandelt Ereignisse vom Typ "read", "security" oder "default". Sie ist gedacht für Plugins, welche ausschließlich Lesezugriffe auf dem Dateisystem oder einer Datenbank durchführen. Diese Gruppe wird eher selten verwendet.
  • Die Gruppe "primary" behandelt alle Ereignisse außer "config". Sie ist gedacht für Plugins welche als Hauptprogramme fungieren.
  • Die Gruppe "default" behandelt alle Ereignisse außer solche vom Typ "security", "config" und "primary". Sie ist gedacht für "sonstige" Plugins, beziehungsweise als Lösung für Entwickler, welche sich unsicher darüber sind, in welche Gruppe sie Ihr Plugin einordnen sollten.
benötigt das Plugin:
ID-Kennung eines Plugins, welches erforderlich ist, damit dieses funktioniert. Benutzen Sie dieses Feld, wenn Sie eine bestehende Anwendung durch neue Funktionen erweitern wollen. Das Auswahlmenü dient nur als Hilfestellung. Es muss nicht unbedingt eine der IDs dieses Menüs verwendet werden.
gehört zu Paket:
benutzen Sie dieses Feld um auszudrücken, dass zwei Plugins zusammen gehören. Tragen Sie dazu in dieses Feld das gemeinsame "Package" ein, zu dem beide gehören.

Schritt 2: Schnittstelle editieren

Der zweite Schritt erlaubt dem Entwickler eigene Aktionen zur die Schnittstelle hinzuzufügen.

Falls Sie nur eine einfache Datenbankanwendung erstellen wollen, können Sie diesen Schritt übergehen. Die meisten Standardaktionen, wie das Anzeigen von Datenbankeinträgen, Suche, Editieren, Löschen oder Einfügen, müssen nicht von Hand geschrieben werden. Diese Aktionen erzeugt das SDK automatisch.

Wenn Sie andere Aktionen festlegen möchten, können Sie hier deren Schnittstelle definieren. Dazu können Vorlagen verwendet werden, welche das SDK vorgibt. Ein händische Erstellung ist ebenfalls möglich. Die Schnittstellen können auch nachträglich von Hand verändert werden.

Formular 4

Für einige Standardaktionen gibt es Vorlagen, welche benutzt werden können. Schauen Sie in die Auswahlliste. Wenn eine Option ausgewählt wurde, erscheint zum Vergleich eine Liste der erzeugten Aktionen. Sie können sich die gesamte Schnittstelle anschauen, indem Sie die Option "Schnittstelle von Hand nachbearbeiten" auswählen.

Formular 5

Eine Schnittstelle enthält folgende Informationen:

Name der Aktion:
Name der Funktion (beliebig). Es sind nur Zeichen von A-Z und 0-9 sowie "_" erlaubt. Schauen Sie sich zum Vergleich die Beispiele an.
Modus:
sollte üblicherweise "Standard" sein. Der abgesicherte Modus ist für den Fall, dass Sie absichtlich Default-Werte verwenden wollen oder müssen.
Templates:
ID-Kennung des Templates, welches verwendet werden soll. Diese Kennung wird im Skin festgelegt. Schauen Sie sich die Skin-Dateien im Verzeichnis "skins/default/*.config" an, oder benutzen Sie das Auswahlmenü als Beispiel! 
Zugriffsbeschränkung:
legt fest, welche Rechte ein Besucher haben muss, damit er diese Aktion aufrufen kann.
Formular 6

Diese Option dient zur Kontrolle, beziehungsweise als Alternative Eingabeoberfläche für erfahrene Nutzer. Sie sehen alle definierten Aktionen und können Änderungen vornehmen.

Vorsicht! Fehler können dazu führen, dass das Plugin nicht korrekt erzeugt werden kann.

Schritt 3: GUI generieren

Es kann für Datenbankanwendungen automatisch eine GUI generiert werden. Dazu wird eine Strukturdatei benötigt, welche die Datenbank beschreibt. Aus den Informationen dieser Datei erzeugt das SDK für jede Tabelle automatisch passende Template-Dateien, sowie die dazu passenden Aktionen und erzeugt zudem die erforderlichen Ergänzungen für die Schnittstelle der Anwendung.

Wenn Sie keine solche Datenbankanwendung erstellen wollen, kann dieser Schritt übergangen werden.

Automatisch erzeugt werden jeweils: pro Tabelle ein Template zum Anzeigen, Editieren, Anlegen und Durchsuchen von Datenbankinhalten, sowie der PHP-Code für die dazu gehörende Aktionen. Außerdem Aktionen, für den Download von Dateien und Bildern aus der Datenbank. Weiterhin wird eine JavaScript-Datei erzeugt, um über Ajax Aktionen auf dem Server auslösen zu können. Zuletzt wird die Strukturdatei selbst im System gespeichert.

Formular 7

Sollten Sie noch keine Strukturdatei geschrieben haben, können Sie eine solche Datei erzeugen. Benutzen Sie dazu das Plugin "DB-Tools". Öffnen Sie das im Administrationsmenü "DB-Tools" / "Import". Wählen Sie eine der Optionen, um eine bereits existierende Datenbank zu importieren. Falls Sie bis jetzt noch keinerlei Vorlage für die Datenbank zur Verfügung haben, lesen Sie bitte das Einführungstutorial. Beachten Sie auch die Beispiele im Kochbuch für Entwickler.

Formular 8

Wenn Sie eine Strukturdatei erzeugt, oder von Hand geschrieben haben, geben Sie bitte hier den Pfad dieser Datei an. Klicken Sie auf "Durchsuchen", wenn Sie sich nicht sicher sind, wo sich diese befindet.

Schritt 4: Installationsroutine erstellen

Sie können in Schritt 4 eigene SQL-Dateien für die Installation Ihrer Datenbank angeben. Dieser Schritt ist optional. Das Framework kann (seit Version 2.8.6) die SQL-Anweisungen für die Installation bei Bedarf automatisch aus der in Schritt 3 angegebenen Strukturdatei erzeugen. Dies funktioniert für: MySQL, MS-SQL, PostgreSQL, Oracle Datenbanken, IBM DB2 und MS Access. Handarbeit ist somit (außer in Ausnahmefällen) unnötig.

Falls für das gewünschte DBMS keine automatische Generierung möglich ist, können Sie eine handgeschriebene SQL-Installationsdatei bereitstellen.

Formular 9

Wählen Sie die Quelldatei im SQL-Format aus, welche die Informationen zur Installation der Datenbank enthält.

Ihre SQL-Installationsdateien finden Sie nach der Generierung des Plugins im Verzeichnis "config/db/.install/". Dieses enthält für jedes unterstützte DBMS Unterverzeichnisse. Hierher können Sie auch nachträglich noch SQL-Dateien von Hand kopieren. Die Datei muss den gleichen Namen haben wie die Strukturdatei und die Endung ".sql" besitzen.

Erzeugen der Anwendung

Zum Abschließen der Konfiguration klicken Sie bitte auf die Schaltfläche "Fertigstellen".

Das SDK produziert als Ausgabe ein Skelett der Anwendung, alle erforderlichen Templates, sowie alle notwendigen Konfigurationsdateien. Diese beinhalten insbesondere: Meta-Informationen des Plugins inklusive Beschreibung der Schnittstelle, Meta-Informationen der verwendeten Dateien, Meta-Informationen der verwendeten Templates.

Das soeben generierte Plugin ist sofort lauffähig. Sie finden die entsprechenden Dateien im Verzeichnis "plugins" beziehungsweise "skins/default", unter der ID-Kennung des Plugins.

Plugin installieren

Um das soeben erzeugte Plugin zu testen:

  1. Öffnen Sie die Datei "index.php" in Ihrem Browser
  2. Öffnen Sie das Administrationsmenü. Sie müssen Administratorrechte besitzen. Achten Sie darauf, dass der Expertenmodus gewählt ist.
  3. Wählen Sie im rechten Menü die Schaltfläche "Liste neu laden".
  4. Suchen Sie Ihr Plugin in der Liste und aktivieren Sie es, indem Sie die Checkbox neben dem Namen anklicken.
  5. Speichern Sie Ihre Änderungen.
  6. Melden Sie sich ab.
  7. Der Name der Anwendung erscheint auf der Sitemap. Klicken Sie darauf um die Anwendung zu starten. (der Eintrag in der Sitemap erscheint nur dann, wenn Sie in der Schnittstelle mindestens 1 Aktion definiert haben, welche den Typ "read" oder "default" und die Zugriffsbeschränkung "0" (=öffentlich) besitzt. Falls nicht, müssen Sie den Namen der gewünschten Aktion über die Adressleiste des Browsers eingeben: index.php?action=my_action. Dieser Mechanismus ist dazu gedacht zu verhindern, dass Plugins, die allein nicht lauffähig sind, oder Adminrechte benötigen, auf der öffentlich zugänglichen Sitemap erscheinen)

Übersetzungen erstellen

Allgemeines

Diese Anwendung benutzt Dateien zum Speichern von Inhalten, die in mehrere Sprache übersetzt werden können. Diese Dateien sind als Pakete zusammengefasst. Jeweils ein Paket passt genau zu einer Übersetzung. Also beispielweise ein deutsches, oder ein englisches Paket. Jedes Paket enthält Texte und Grafiken. Die in den Textdateien beschriebenen IDs sind Texten zugeordnet. Die IDs entsprechen exakt den dazu passenden Token in den Skinpaketen.

Übersetzungen editieren

Wenn Sie einen Fehler in einem Übersetzungspaket gefunden haben und korrigieren wollen, finden Sie die entsprechenden Dateien im Verzeichnis "languages/". Jeweils ein Unterverzeichnis pro Paket. Jedes der Pakete enthält Dateien, welche passend den Plugins benannt sind, für die sie bestimmt sind.

Das Editieren der Dateien ist möglichst einfach gestaltet. Öffnen Sie die Datei in einem Texteditor Ihrer Wahl. Die Dateien sind in einem XML-ähnlichen Format geschrieben. Vermeiden Sie die Verwendung von HTML-Tags in diesen Dokumenten. Das Benutzen von Embedded Tags ist erlaubt. Beachten Sie, dass keine Zeilenumbrüche innerhalb des Fließtextes gestattet sind. Um einen Zeilenumbruch einzufügen, benutzen Sie den Emb. Tag [br].

Wenn Sie Übersetzungen editieren empfiehlt es sich, nicht die Originaldaten zu überschreiben. Machen Sie stattdessen eine Kopie der Dateien als neues Sprachpaket.

neue Sprachpakete erzeugen

Um die Textmeldungen der Anwendung in eine neue Sprache zu übersetzen, Speichern Sie eine Kopie des Verzeichnisses "languages/de" und der zugehörigen Konfigurationsdatei "deutsch.config" unter einem neuen Namen. Sinnvollerweise passend zur Sprache, für welche die Übersetzung bestimmt ist. Beispielsweise "languages/es".

Sie haben die Möglichkeit Ihre persönlichen Informationen, wie Name des Autors, oder eine kurze Beschreibung unterzubringen. Editieren Sie diese Einstellungen in der Konfigurationsdatei des Sprachpakets. Außerdem können Sie eine passende Grafik einfügen. Üblicherweise eine Landesflagge. Ersetzen Sie dazu die Datei "flagge.gif".  Den Namen der Datei legen Sie in der Konfigurationsdatei unter der ID "LANGUAGE_INFO.LOGO" fest.

Coding Principles

Allgemeines

"Coding principles" sind grundsätzliche Regeln zum Schreiben und Formatieren von PHP-Code. Die Einhalt dieser Regeln hilft, Quellcode einheitlich, lesbar und übersichtlich zu halten.

Verschiedene Autoren die gemeinsam den gleichen Quellcode bearbeiten, haben oft gegensätzliche Auffassungen davon, wie gut lesbarer Code aussehen sollte. Um dennoch eine einheitliche Schreibweise und gleichbleibende Qualität sicherzustellen ist es notwendig, sich auf die Einhaltung gemeinsamer Regeln zu einigen. Es darf nicht möglich sein von der Formatierung des Quellcodes auf den Autor zu schließen.

PHP-Tags und Dateiformate

Alle Skripte müssen die Dateiendung *.php benutzen und müssen in UTF-8 kodiert sein. Zeilenumbrüche müssen das Linux-Format benutzen (LF statt CRLF oder CR).

Verwenden Sie für Skript-Tags die Schreibweise <?php ... ?> mit schließendem Tag am Ende der Datei. Short-Tags (<? ... ?>) und andere Schreibweisen sind nicht gestattet.

Der geschriebene Code darf bei aktiviertem Error-Reporting keine E_WARNING oder E_NOTICE verursachen. Setzen Sie zum Testen "error_reporting(E_ALL);".

Eine Zeile Quellcode sollte nicht länger als 120 Zeichen sein.

Einrückung und Kommentare

Der Quellcode sollte mit 4 Leerzeichen eingerückt werden. Verwenden Sie keine Tabulatoren.

Für Kommentare verwenden Sie für mehrzeilie Kommentare stets /* comment */. Für einzilige Kommentare // comment. Nicht gestatttet ist die Verwendung von # comment. Alle Kommentare müssen auf Englisch geschrieben werden.

Im Folgenden ein Beispiel:

<?php
/* multi-line
 * comment
 */
function foo()
{
    // single-line comment
    foreach ($input as $key => $element)
    {
        $element = strip_tags( (string) $element);
        if (preg_match("/\//", $key)) {
            $key = preg_replace("/\//", ".", $key);
            Hashtable::set($output, $key, $element);
        } else {
            $output[$key] = $element;
        }
    } // end foreach
}
?>

Deklaration und Gültigkeit von Variablen

Variablen müssen auf Englisch und in CamelCase benannt werden - also $debugSourcePath anstatt $debug_source_path. Der erste Buchstabe wird klein geschrieben.

Viele typische Fehler in PHP rühren daher, dass Programmierer annehmen, eine Variable sei unbenutzt, von einem bestimmten Typ, oder würde an nach einer bestimmten Code-Zeile nicht mehr verwendet. Beachten Sie: eine Variable immer so spät wie möglich deklarieren und so früh wie möglich löschen. Variablen müssen stets initialisiert werden.

<?php
// Beginn der Lebensdauer
assert('!isset($variable); // Cannot redeclare $variable');
$variable = 0;

// ...

// Wird die Variable nicht mehr benötigt, sollte sie explizit gelöscht werden
unset($variable);
// Ende der Lebensdauer
?>

If und Else

Die Verwendung von Klammern { } ist obligatorisch, selbst in Fällen wo diese technisch nur optional ist. Verwenden Sie zur besseren Lesbarkeit Leerzeichen zwishen den Vergleichsoperatoren.

<?php
if ($test1 === 1) {
    $command1;
} elseif ($test2 === 2 || $test === 3) {
    $command2;
} else {
    $commandN;
} // end if
?>

Try und Catch

Falls Sie die Klasse "Exception" abfangen wollen, so muss dies der letzte Catch-Block der Anweisung sein.

<?php
try {
    $command1;
} catch (FooException $e) {
    $command2;
} catch (BarException $e) {
    $command3;
} catch (Exception $e) {
    $commandN;
}
?>

Switch

Beachten Sie für die Switch-Anweisung die Einrückung und die Zeilenumbrüche, diese dienen der Lesbarkeit.

Alle Case-Anweisungen müssen mit einer Break-Anweisung geschlossen werden. Ausnahmefälle müssen ausdrücklich mit dem Kommentar "// fall through" anstatt "break" dokumentiert werden.

Der Default-Statement ist obligatorisch und darf nicht fehlen, selbst wenn es leer ist.

<?php
switch ($variable)
{
    case 1:
        $command1;
    break;
    case 2:
    case 3:
        $command2;
    break;
    case 4:
        $command4;
    // fall through
    default:
        $commandN;
    break;
} // end switch
?>

For, Foreach und While

Achten Sie auf die Zeilenumbrüche, diese dienen der Lesbarkeit.

Prüfen Sie vor der Schleife unbedingt ob die verwendeten Schleifenvariablen bereits benutzt sind, da PHP diese sonst überschreibt. Löschen Sie Schleifenvariablen nach Verwendung mit unset().

<?php
assert('!isset($i); // Cannot redeclare $i');
for ($i = 0; $i < sizeOf($input); $i++)
{
    $command1;
} // end for
unset($i);

assert('!isset($key); // Cannot redeclare $key');
assert('!isset($element); // Cannot redeclare $element');
foreach ($input as $key => $element)
{
    $command2;
} // end foreach
unset($key, $element);

while ($test)
{
    $command3;
} // end while
?>

Klassen und Funktionen

Verwenden Sie CamelCase-Schreibweise. Der erste Buchstabe muss bei Funktionen klein, und bei Klassen groß geschrieben werden.

Die Namen von privaten Funktionen müssen mit einem Unterstrich beginnen. Die Namen privater Variablen dürfen (müssen jedoch nicht) ebenfalls mit einem Unterstrich beginnen. In allen anderen Fällen muss der Name immer mit einem Buchstaben (a-z) beginnen.

Empfehlung: der Namen einer Funktion sollte aus einem Verb und einem Substantiv bestehen, z.Bsp.: "getBeer()" oder "setContent()". Ist der Rückgabewert ein Array, so verwenden Sie den Plural, z.Bsp.: "getLines()".

Zur Dokumentation von Klassen und Funktionen muss PHP-Doc (http://www.phpdoc.org/) verwendet werden.

Die Tags @param, @return, @var und @package sind Pflicht. Dokumentation muss in Englisch verfasst sein.

Vermeiden Sie es Variablen als "public" zu kennzeichnen. Verwenden Sie stattdessen Zugriffsfunktionen ("Getter" und "Setter").

<?php
/**
 * <<Stereotype>> name
 *
 * The purpose of this class is ...
 *
 * @access      public
 * @package     package
 * @subpackage  subpackage
 */
class MyClass extends BaseClass implements Foo, Bar
{
    /**
     * Short description
     *
     * @access  private
     * @var     string
     */
    private $var0 = "";

    /**#@+
     * Block-declaration
     *
     * @access  private
     */

    /** @var  array */  private $var1 = array();
    /** @var  int   */  private $var2 = 0;
    /** @var  View  */  private $var3 = null;
    /** @var  array */  private $var4 = array();
    /** @var  array */  private $var5 = array();

    /**#@-*/

    /**
     * Constructor
     *
     * Long description.
     *
     * @access  public
     * @param   string  $filename  path to file.ext
     */
    public function __construct($filename)
    {
        assert('is_string($filename); // Wrong type for argument 1. String expected');
        $command1;
    }

    /**
     * Short description
     *
     * Long description.
     *
     * @access  public
     * @param   string  $id  alpha-numeric, unique identifier
     * @return  int
     */
    public function getVar($filename)
    {
        assert('is_string($filename); // Wrong type for argument 1. String expected');
        // ...
        assert('is_int($result); // Wrong result type. Integer expected');
        return $result;
    }

}
?>

API-Dokumentation

Die API-Dokumentation enthält Informationen für Entwickler, die eigene Erweiterungen schreiben wollen. Hier finden Sie Beschreibungen zu Schnittstellen und Beispiele zu allen verfügbaren Klassen und Funktionen der Software.

Klicken Sie hier, um die API-Dokumentation zu öffnen.

Kochbuch

Arbeiten mit Datenbanken

Allgemeines zum Verständnis

Welche Features werden unterstützt?

Das Yana-Framework bietet eine API zum Arbeiten mit Datenbanken, welche auf PEAR-DB basiert. Diese API erweitert die Fähigkeiten von PEAR um folgende Features:

Welche Features werden nicht unterstützt?

Es gibt einige Features welche die FlatFile-Datenbank zur Zeit nicht unterstützt, die aber für eine zukünftige Version geplant sind.

Es gibt einige Features welche in Datenbankschemata zur Zeit nicht unterstützt werden, aber für zukünftige Versionen geplant sind.

Wie erstelle ich eine Verbindung zu einer Datenbank?

Voraussetzung ist eine Schemadatei. Die Schemadateien müssen sich im Verzeichnis "config/db/" befinden und die Dateiendung ".config" besitzen.

Datenbankverbindung mit den aktuellen Verbindungsdaten herstellen
<?php
global $YANA;
$name_der_strukturdatei = "guestbook";
$datenbankverbdinung = $YANA->connect($name_der_strukturdatei);
?>

Die Verbindungsdaten für die Datenbank (wie Hostadresse, Nutzername und Passwort) werden vom Nutzer im Administrationsmenü eingegeben. Sie müssen diese im Quellcode NICHT angeben.

Wenn Sie keine Strukturdatei verwenden möchten, können Sie diese Angabe frei lassen. Dies wird jedoch in einer Produktionsumgebung nicht empfohlen. In diesem Fall wird das Framework versuchen, die Angaben selbst zu ermitteln. Falls dies fehlschlägt ist die Datenbankverbindung nicht nutzbar.

Datenbankverbindung mit individuellen Verbindungsdaten herstellen

Wenn Sie eine Verbindung mit einer Datenbank herstellen, aber die Verbindungsdaten selbst angeben wollen, dann gehen Sie wie folgt vor:

<?php
/* Die Verbindungsdaten werden als assoziatives Array angegeben: */
$verbindungsdaten = array(
    'DBMS' => 'mysql',
    'HOST' => 'localhost',
    'PORT' => 0,
    'USERNAME' => 'nutzername',
    'PASSWORD' => 'passwort',
    'DATABASE' => 'name_der_datenbank'
);

/* Um die YANA-API zur Kommunikation mit der Datenbank zu benutzen schreiben Sie: */

$datenbank_server = new DbServer($verbindungsdaten);
$yana_api = new DbStream($datenbank_server);

/* Um die PEAR-API zur Kommunikation mit der Datenbank zu benutzen schreiben Sie: */

$datenbank_server = new DbServer($verbindungsdaten);
$pear_api = $datenbank_server->get();

/* Um die PEAR-API mit den Standardverbindungsdaten zu benutzen schreiben Sie: */

$datenbank_server = new DbServer();
$pear_api = $datenbank_server->get();
?>

Wie prüfe ich, ob im Administrationsmenü die Datenbankverbindung aktiviert ist?

<?php
if (YANA_DATABASE_ACTIVE === true) {
    print "Datenbank ist aktiviert";
} else if (YANA_DATABASE_ACTIVE === false) {
    print "Datenbank ist NICHT aktiviert";
}
?>

Wie erstelle ich eine Datenbankabfrage?

Dazu bietet die API die Funktion $db->get(string $key). Diese führt eine Select-Anfrage auf der Datenbank aus und liefert den Wert an der Stelle zurück, welche mit dem Argument $key angegeben wurde.

<?php
global $YANA;
$db = $YANA->connect("guestbook");

/*
   Es gilt folgende Syntax:

   $db->get(
            string "$tabelle.$zeile.$spalte",
            string $where,
            string $order_by,
            int $offset,
            int $limit
           );

   Beispiel:
   $value = $db->get("table.1.field","row1=wert1,row2=wert2","row1",0,1);

   erzeugt folgende SQL-Anfrage:
   SELECT field from table where primary_key = "1" and row1 like '%wert1%' and row2 like '%wert2%' order by row1 limit 1;
*/

/* Feld ausgeben */
$value = $db->get("table.1.field");
/*
   erzeugt folgende SQL-Anfrage:
   SELECT field from table where primary_key = "1";
*/

/* Spalte ausgeben: */
$column = $db->get("table.*.field");
foreach ($column as $row => $value)
{
    print "<p>Value of 'field' in row '$row' = $value</p>";
}
/*
   erzeugt folgende SQL-Anfrage:
   SELECT field from table;
*/

/* Zeile ausgeben: */
$row = $db->get("table.2");
foreach ($row as $column => $value)
{
	echo "<p>Value of column '$column' in row '2' = $value</p>";
}
/*
   erzeugt folgende SQL-Anfrage:
   SELECT * from table where primary_key = "2";
*/

/* Tabelle ausgeben: */
$table = $db->get("table");
foreach ($table as $index => $row)
{
	foreach ($row as $column => $value)
	{
		echo "<p>Value at 'table.$index.$column' = $value</p>";
	}
}
/*
   erzeugt folgende SQL-Anfrage:
   SELECT * from table;
*/
?>

Wie führe ich INSERT- / UPDATE-Statements aus?

Dazu verwenden Sie die Funktion $db->insert($key,$value). Diese fügt den Wert "value" an der Stelle "key" ein. Dabei kann es sich entweder um eine Zeile oder eine Tabellenzelle handeln. Das Einfügen von ganzen Tabellen oder Spalten ist nicht möglich.

Beim ersten Aufruf der Funktion wird automatisch eine Transaktion gestartet. Benutzen Sie die Funktion $db->write() um ein COMMIT der Daten auszulösen. Wenn eine der Anweisungen in der Transaktion fehlschlägt, wird automatisch ein CALLBACK ausgeführt.

Falls die Zeile nicht existiert, wird ein die SQL-Anweisung "insert" benutzt, sonst "update".

Die Funktion gibt bei Erfolg "true" zurück und "false" sonst.

Bitte beachten Sie: die SQL-Anweisung wird erst ausgeführt, wenn die Funktion $db->write() aufgerufen wird.

Im Folgenden einige Beispiele:

<?php
global $YANA;
$db = $YANA->connect("guestbook");

/* Neue Zeile einfügen: */
$db->insert("table.*",array("row1"=>"wert1","row2"=>"wert2"));
$db->write();

/* Zeile aktualisieren: */
$db->insert("table.2",array("row1"=>"wert1","row2"=>"wert2"));
$db->write();

/* Zelle aktualisieren: */
$db->insert("table.2.row1","wert1");
$db->write();

/* Transaktion durchführen: */
$db->insert("table.*",array("row1"=>"wert1","row2"=>"wert2"));
$db->insert("table.*",array("row1"=>"wert3","row2"=>"wert4"));
$db->insert("table.1.row3","wert1");
$db->write();
?>

Wie führe ich DELETE-Statements aus?

Dazu verwenden Sie die Funktion $db->remove($key). Diese löscht den Datensatz an der Adresse "key" aus der Tabelle. Die Funktion gibt bei Erfolg "true" zurück und "false" sonst. Es können nur Datensätze gelöscht werden. Keine Tabellen, Zellen oder Spalten.

Beachten Sie folgende Beschränkung: aus Sicherheitsgründen wird pro Aufruf stets maximal 1 Datensatz gelöscht. Wenn Sie mehrere Datensätze löschen wollen, müssen Sie die Funktion mehrmals aufrufen. Diese Einschränkung soll verhindern, dass jemand durch Unachtsamkeit oder aus einem Versehen eine gesamte Tabelle löschen kann.

Bitte beachten Sie: die SQL-Anweisung wird erst ausgeführt, wenn die Funktion $db->write() aufgerufen wird.

<?php
global $YANA;
$db = $YANA->connect("guestbook"); /* Die zweite Zeile löschen: */ $db->remove("table.2"); $db->write(); /** * erzeugt folgende SQL-Anfrage: * DELETE FROM table WHERE primary_key = "2" LIMIT 1; */ /* Die ganze Tabelle "table" löschen: */ for ($i=0; $i < $db->length($table); $i++) { $db->remove("table.*"); } $db->write(); /** * erzeugt folgende SQL-Anfrage: * DELETE FROM table WHERE primary_key = "2" LIMIT 1; */ ?>

Wie finde ich heraus wie viele Datensätze eine Tabelle hat?

<?php
global $YANA;
$db = $YANA->connect("guestbook"); if ($db->length("table") === 0) { print "Die Tabelle 'table' ist leer."; } else { print "Die Tabelle 'table' enthält ".$db->length("table")." Datensätze."; } ?>

Wie finde ich heraus ob eine Tabelle / Datensatz existiert?

<?php
global $YANA;
$db = $YANA->connect("guestbook"); /* Datenbankverbindung prüfen: */ if ($db->exists() === true) { print "Die Datenbankverbindung ist verfügbar."; } else if ($db->exists() === false) { print "Die Datenbankverbindung ist NICHT verfügbar"; } /* Prüfen ob Tabelle existiert: */ if ($db->exists("table") === true) { print "Die Tabelle 'table' existiert."; } else if ($db->exists("table") === false) { print "Es gibt keine Tabelle mit dem Namen 'table'."; } /* Prüfen ob Datensatz existiert: */ if ($db->exists("table.2") === true) { print "Der Datensatz '2' in der Tabelle 'table' existiert."; } else if ($db->exists("table.2") === false) { print "Es gibt keinen Datensatz '2' in der Tabelle 'table'."; } /* Prüfen ob Feld existiert und einen Wert hat: */ if ($db->exists("table.2.field") === true) { print "Das Feld 'field' im Datensatz '2' in Tabelle 'table' hat einen Wert."; } else if ($db->exists("table.2.field") === false) { print "Das Feld 'field' im Datensatz '2' in Tabelle 'table' existiert nicht oder ist NULL."; } /* Prüfen ob mindestens 1 Feld existiert, dass NOT NULL ist: */ if ($db->exists("table.*.field") === true) { print "Die Spalte 'field' in Tabelle 'table' existiert."; } else if ($db->exists("table.*.field") === false) { print "Die Spalte 'field' in Tabelle 'table' existiert nicht oder alle Werte sind NULL."; } ?>

Wie erstelle ich eine Installationsroutine für meine Tabellen?

Das manuelle Erstellen von Installationsroutinen für das Yana Framework ist nicht erforderlich.

Das Yana Framework hat eine generische Installationsroutine für Datenbanken, welche Sie im Administrationsmenü, in der Basiskonfiguration im Menü "Datenbank Setup" finden. Über dieses Menü kann ein Nutzer alle Tabllen installieren oder Inhalte zwischen dem DBMS und der FlatFile-Datenbank synchronisieren.

Screenshot
Abbildung: Herstellen einer Verbindung und Installation von Datenbanken

Die dafür erforderlichen SQL-Anweisungen erstellt das Framework automatisch aus der Strukturdatei Ihrer Datenbank. Der folgende Quellcode zeigt, wie Sie den durch das Framework generierten Code einsehen können.

<?php
$db = $YANA->connect('guestbook');
$dbe = new DbExtractor($db);

// Erzeugen der "Create Table ..."-Anweisungen für MySQL
$sql = $dbe->createMySQL();

// es existieren einige weitere Funktionen für andere DBMS
$sql = $dbe->createPostgreSQL();
$sql = $dbe->createMSSQL();
$sql = $dbe->createMSAccess();
$sql = $dbe->createDB2();
$sql = $dbe->createOracleDB();

// Ergebnis ausgeben
print implode("\n", $sql);
?>

Falls der generierte Code nicht Ihren Erwartungen entspricht, können Sie diesen durch eine eigene SQL-Datei ersetzen. Kopieren Sie diese bitte in das Verzeichnis "config/db/.install/{DBMS}", wobei Sie statt {DBMS} das Unterverzeichnis wählen, welches dem gewünschten DBMS entspricht. Die Datei "config/db/.install/readme.txt", enthält eine Liste der unterstützten DBMS und der Namen der für diese vorgesehenen Verzeichnisse. Sie müssen nicht für alle DBMS eigene Dateien hinterlegen. Falls eine erforderliche Datei nicht existiert, wird das Framework (wie zuvor) automatisch die notwendigen SQL-Anweisungen selbst erzeugen.

Weitere Details finden Sie in der API-Dokumentation der Klasse: "DbExtractor".

Wie importiere ich eine SQL-Datei mit DDL-Anweisungen?

<?php
global $YANA;
$db = $YANA->connect("guestbook");
$db->importSQL('data.sql');
?>

Wie exportiere ich Daten in eine CSV-Datei?

<?php
global $YANA;
$db = $YANA->connect("guestbook");
$csv = $db->toString("table");
file_put_contents("table.csv", $csv);
?>

Arbeiten mit dem Schema einer Datenbank

Wie exportiere ich ein Datenbankschema in eine Datei?

<?php
global $YANA;
$db = $YANA->connect("guestbook");
$db->exportStructure("guestbook.config");
?>

Aufbau einer Strukturdatei

Strukturdateien sind im mit XML-verwandten SML-Format geschrieben (siehe auch das Kapitel: "Das SML Dateiformat"). Im Folgenden finden Sie eine informelle, Grobübersicht zu den einzelnen Elementen.

Der folgende informelle Text erläutert die Struktur *

DATABASE {
    use_strict    (true | false)
    readonly?     (true | false)
    description?  #string
    include?      (#string | #array)

    TABLES {
        readonly?      (true | false)
        description?   #string
        primary_key    #string
        profile_key?   #string
        foreign_keys?  #array

        CONSTRAINT?    { ... }
        TRIGGER?       { ... }

        CONTENT {
            readonly?     (true | false)
            description?  #string
            type          #string
            length?       #numeric
            precision?    #numeric
            required?     (true | false | AUTO)
            default?      #string
            unique?       (true | false)
            index?        (true | false)

            CONSTRAINT?   { ... }
            TRIGGER?      { ... }

            /* nur für numerische Datentypen */
            unsigned?     (true | false)
            zerofill?     (true | false)

            DISPLAY? {
                HIDDEN {
                    new?     (true | false)
                    edit?    (true | false)
                    select?  (true | false)
                    search?  (true | false)
                }
                READONLY {
                    new?   (true | false)
                    edit?  (true | false)
                }
                /* nur für Typ "array" */
                numeric  (true | false)
            }

            /* nur für Typ "image" */
            width?       #numeric
            height?      #numeric
            ratio?       (true | false)
            background?  #array
        }
    }
}

CONSTRAINT {
    select?  #string
    insert?  #string
    update?  #string
    delete?  #string
}

TRIGGER {
	before_insert?  #string
	before_update?  #string
	before_delete?  #string
	after_insert?   #string
	after_update?   #string
	after_delete?   #string
}

* Hilfe: Syntaktische Elemente der Datei werden blau dargestellt. Die möglichen Werte und / oder Datentypen, welche diese Elemente enthalten dürfen, werden hinter den Elementen aufgelistet. Datentypen werden durch eine Raute (#) gekennzeichnet. Es werden folgende Datentypen verwendet: #string = ein Text, #numeric = eine Zahl, #array = ein Listentyp. Falls mehrere Werte oder Datentypen erlaubt sind, werden diese in runden Klammern, durch ein Pipesymbol (|) getrennt aufgelistet. Ein Fragezeichen (?) gibt an, dass das betreffende Element optional ist.

Der nachfolgende Abschnitt erläutert die einzelnen Elemente im Detail und liefert Beispiele.

Wie schreibe ich ein eigenes Datenbankschema?

Schema-Dateien haben die Endung "*.config" und werden im Verzeichnis "config/db/" gespeichert. Eine Verbindung auf Grundlage einer Schema-Datei wird hergestellt über den PHP-Code: $YANA->connect("Name der Datei ohne Dateiendung");

Beachten Sie, dass für die Editoren "ConTEXT" und "PSPad" Code-Templates zur Verfügung stehen, welche Ihnen gerade beim Erzeugen von Datenbankschemata viel Schreibarbeit abnehmen können. Sollten Sie einen dieser beiden Editoren verwenden, installieren Sie nach Möglichkeit zunächst diese Templates bevor Sie fortfahren.

Das folgende Listing zeigt ein Schema mit allen Elementen und alle gültigen Belegungen. Existieren mehrere mögliche Varianten, dann sind diese die verschiedenen Möglichkeiten durch eine Pipe '|' voneinander getrennt. Bezeichner, die frei gewählt werden können, sind im Text fett hervorgehoben.

/* Das Feld "USE_STRICT" legt fest, ob Queries zur Laufzeit
 * gegen das Schema validiert werden oder nicht.
 */
<USE_STRICT>true|false</USE_STRICT>

/* Das Feld "READONLY" ist optional. Default = false
 */
<READONLY>true|false</READONLY>

/* Das Feld "DESCRIPTION" ist optional und kann eine Beschreibung,
 * oder den Namen der Datenbank enthalten
 */
<DESCRIPTION>Text</DESCRIPTION>

/* Das Feld "INCLUDE" hat die gleiche Bedeutung wie der gleichnamige
 * Befehl in PHP. Es importiert eine oder mehrere Datenbankschemata in die
 * aktuelle Datei.
 * Der Dateiname wird ohne Dateiendung angegeben.
 * Also zum Beispiel: <INCLUDE>user</INCLUDE> um die Datenbank "user" zu
 * importieren, die in der Datei "config/db/user.config" beschrieben wird.
 */
<INCLUDE>Datenbankschema</INCLUDE>

/* Um mehrere Dateien zu importieren verwenden Sie folgende Schreibweise:
 */
<INCLUDE>
	<0>1.Schema</0>
	<1>2.Schema</1>
	<2>3.Schema</2>
</INCLUDE>

/* Constraints sind boolesche Ausdrücke in PHP-Syntax.
 * Sie können mit einer bestimmten SQL-Aktion verknüpft werden.
 * Ergibt der Ausdruck "false" wird die entsprechende Query nicht
 * abgeschickt und ein Log-Eintrag geschrieben. Andernfalls wird die
 * Aktion fortgesetzt.
 *
 * In Constraints können Sie keine Funktionen aufrufen, mit einer einzigen
 * Ausnahme: preg_match();
 * Außerdem haben Sie Zugriff auf folgende Konstanten:
 * $VALUE      = (für INSERT, UPDATE) Wert der eingefügt wird
 * $PERMISSION = Zugriffslevel des Nutzers, der die Aktion ausgelöst hat
 * $OPERATION  = SQL-Kommando das gerade durchgeführt wird (SELECT, INSERT, ...)
 * $TABLE      = Name der Zieltabelle (meist die aktuelle Tabelle)
 * $FIELD      = Name der Zielspalte (falls angegeben)
 * $ID         = Id des aktuellen Profils (seit Version 2.8.9)
 *
 * Beispiele:
 * <SELECT>true</SELECT>
 * <UPDATE>false</UPDATE>
 * <UPDATE>$VALUE > 0 && $VALUE < 500</UPDATE>
 * <INSERT>$PERMISSION > 50</INSERT>
 * <INSERT>preg_match('/^[\w\d-_]*$/i', $VALUE)</INSERT>
 *
 * Constraints gibt es in YANA seit Version 2.8 .
 */
<CONSTRAINT>
	<SELECT>PHP-Code</SELECT>
	<INSERT>PHP-Code</INSERT>
	<UPDATE>PHP-Code</UPDATE>
	<DELETE>PHP-Code</DELETE>
</CONSTRAINT>

/* Trigger sind Miniaturprogramme in PHP-Syntax.
 * Sie werden an eine bestimmte SQL-Aktion geknüpft und automatisch ausgeführt bevor
 * oder nachdem das SQL Statement ausgeführt wurde.
 *
 * DIESE Trigger unterscheiden sich von Triggern direkt in einer Datenbank.
 * 1) PHP kann verwendet werden,
 * 2) unabhängig vom DBMS, aber:
 * 3) kein direkter Zugriff auf die Datenbank.
 *
 * Diese Trigger eignen sich vor allem für Logging und Modifizieren von Eingabedaten.
 *
 * Außerdem haben Sie Zugriff auf folgende Konstanten:
 * $VALUE      = (für INSERT, UPDATE) Wert der eingefügt wird
 * $PERMISSION = Zugriffslevel des Nutzers, der die Aktion ausgelöst hat
 * $OPERATION  = SQL-Kommando (BEFORE_INSERT, AFTER_UPDATE, ...)
 * $TABLE      = Name der Zieltabelle (meist die aktuelle Tabelle)
 * $FIELD      = Name der Zielspalte (falls angegeben)
 * $ID         = Id des aktuellen Profils (seit Version 2.8.9)
 *
 * Beispiele:
 * <BEFORE_INSERT>$VALUE = md5($VALUE);true</BEFORE_INSERT>
 * <AFTER_DELETE>if($VALUE){print 'Erfolgreich gelöscht.';}else{print 'Fehler.';}</AFTER_DELETE>
 */
<TRIGGER>
	<BEFORE_INSERT>PHP-Code</BEFORE_INSERT>
	<BEFORE_UPDATE>PHP-Code</BEFORE_UPDATE>
	<BEFORE_DELETE>PHP-Code</BEFORE_DELETE>
	<AFTER_INSERT>PHP-Code</AFTER_INSERT>
	<AFTER_UPDATE>PHP-Code</AFTER_UPDATE>
	<AFTER_DELETE>PHP-Code</AFTER_DELETE>
</TRIGGER>

/* Wie Sie vielleicht schon vermutet haben: die Option READONLY=true
 * und der Constraint UPDATE=false haben beide den gleichen Effekt.
 */

/* Hier folgt die Definition der Tabellen.
 */
<TABLES>
	<Name der Tabelle>
		<READONLY>true|false</READONLY>
		<DESCRIPTION>Label der Tabelle</DESCRIPTION>

		<CONSTRAINT>
			<SELECT>PHP-Code</SELECT>
			<INSERT>PHP-Code</INSERT>
			<UPDATE>PHP-Code</UPDATE>
			<DELETE>PHP-Code</DELETE>
		</CONSTRAINT>
		<TRIGGER>
			<BEFORE_INSERT>PHP-Code</BEFORE_INSERT>
			<BEFORE_UPDATE>PHP-Code</BEFORE_UPDATE>
			<BEFORE_DELETE>PHP-Code</BEFORE_DELETE>
			<AFTER_INSERT>PHP-Code</AFTER_INSERT>
			<AFTER_UPDATE>PHP-Code</AFTER_UPDATE>
			<AFTER_DELETE>PHP-Code</AFTER_DELETE>
		</TRIGGER>

/* Im Feld "PRIMARY_KEY" ist der Name der Spalte anzugeben, welche den Primärschlüssel enthält.
   (in Fachliteratur siehe unter dem Stichwort: "primary key constraint")
 */
		<PRIMARY_KEY>Name der Spalte</PRIMARY_KEY>

/* Im Feld "PROFILE_KEY" kann der Name einer Spalte angegeben werden, welche den Profilschlüssel enthält.

   Sinn und Zweck:
   Sie können die Datensätze einer Tabelle einem Profil zuordnen.
   Wenn Sie das tun, sieht ein Nutzer jeweils nur die Datensätze des gerade ausgewählten Profils.

   Erzeugen eines "profile key constraint":
   1) Fügen Sie der Tabelle eine Spalte vom Typ "profile" hinzu
   2) Setzen Sie die Eigenschaft "required" dieser Spalte auf "AUTO"
   3) Setzen Sie die Eigenschaft "profile_key" der Tabelle auf den Namen der Spalte

   (Dies ist ein Spezialfall eines "compound primary key" - also eines "primary key constraint".
   Ein "Spezialfall" deshalb, weil der Schlüssel ein virtueller Schlüssel ist.
   Das heißt, dass die technische Handhabung für den Nutzer vollständig transparent geschieht.
   Sie können diesen Constraint nachträglich entfernen und der Primärschlüssel bleibt dennoch
   gültig. Das bedeutet auch, dass Sie diesen Constraint nachträglich hinzufügen oder entfernen
   können, ohne etwas am Quellcode Ihres Plugins ändern zu müssen. Prüfung und Auflösung der
   Profilschlüssel geschieht auf Ebene des DB-Layer. Dies bedeutet auch, dass es aus Sicht
   der Sicherheit Ihrer Webanwendung praktisch unmöglich ist, einen "profile key" constraint
   zu umgeben. Dieses Feature wurde eingeführt in Version 2.9.)
 */
		<PROFILE_KEY>Name der Spalte</PROFILE_KEY>

/* Im Feld "FOREIGN_KEYS" kann eine Liste von Fremdschlüsseln angegeben werden.
   (in Fachliteratur siehe unter dem Stichwort: "foreign key constraint")
 */
		<FOREIGN_KEYS>
			<Name der Spalte>Name der Zieltabelle</Name der Spalte>
			<andere Spalte>andere Zieltabelle</andere Spalte>
		</FOREIGN_KEYS>

/* Hier folgt die Definition der Tabellenspalten.
 */
		<CONTENT>
			<Name der Spalte>
				<READONLY>true|false</READONLY>

				<CONSTRAINT>
					<SELECT>PHP-Code</SELECT>
					<UPDATE>PHP-Code</UPDATE>
				</CONSTRAINT>
				<TRIGGER>
					<BEFORE_UPDATE>PHP-Code</BEFORE_UPDATE>
					<AFTER_UPDATE>PHP-Code</AFTER_UPDATE>
				</TRIGGER>

/* Im Feld "DESCRIPTION" kann ein Beschriftung für diese Spalte angegeben werden.
 * Sie können hier auch %TOKEN% verwenden, welche Sie zum Beispiel in Ihrem Programm,
 * oder als Sprachdatei festlegen, um eine Beschriftung in mehreren Sprachen anbieten
 * zu können.
 */
				<DESCRIPTION>Label der Spalte</DESCRIPTION>

/* Die primitiven, skalaren Datentypen integer, float und string entsprechen ihrem
 * Äquivalent in PHP. Zusätzlich wurden weitere nützliche Datentypen eingeführt.
 *
 * mail    = prüft beim Eintragen automatisch, ob der Wert eine gültige Mailadresse ist.
 * ip      = prüft beim Eintragen automatisch, ob der Wert eine gültige IP-Adresse ist.
 * text    = für Eingaben aus Textarea-Feldern, führt automatisch zusätzliche Prüfungen
 *           zum Schutz vor Flooding durch.
 * select  = ein Aufzählungsdatentyp, dessen Elemente im Feld "DEFAULT" definiert werden,
 *           siehe unten.
 * array   = kann verwendet werden, um PHP-Arrays zu speichern. Diese werden beim Auslesen
 *           des Wertes aus der Datenbank automatisch wieder umgewandelt.
 * image   = wird verwendet um Grafiken zu speichern. Bearbeitet Dateiuploads, die
 *           Prüfung und Konvertierung der Grafik und generiert automatisch Thumbnails.
 * file    = dieser Typ dient dem Speichern von Dateien ("binary large objects").
 *           Die Dateien selbst verbleiben nach dem Upload aus Gründen der besseren Performance
 *           im Dateisystem. Um Speicherplatz zu sparen, werden Sie automatich GZip-komprimiert.
 *           In der Datenbank wird lediglich der Dateiname gespeichert. Beim Abruf der Spalte
 *           wird der Name und Pfad der komprimierten Datei als Ergebnis zurückgeliefert.
 */
				<TYPE>integer|float|string|text|url|ip|mail|time|select|array</TYPE>

				<LENGTH>positive integer</LENGTH>

/* Für den Datentyp "float" kann mit "PRECISION" die Anzahl der Nachkommastellen festgelegt werden.
 */
				<PRECISION>positive integer</PRECISION>

/* Das Feld "REQUIRED" legt fest ob ein Feld NULLABLE ist oder nicht.
 */
				<REQUIRED>true|false</REQUIRED>

/* Das Feld "DEFAULT" legt einen Wert fest, der automatisch verwendet wird, wenn beim
 * Anlegen des Datensatzes keine anderen Angaben gemacht werden.
 */
				<DEFAULT>ein Defaultwert</DEFAULT>

/* Das Feld "UNIQUE" kann entweder den Wert true, oder false annehmen, wobei false der
 * Defaultwert ist. Ist UNIQUE=true so darf kein Wert in dieser Spalte mehr als 1 Mal
 * vorkommen. Das bedeutet, jeder Wert ist eindeutig (eng. "unique").
 * Man verwendet diese Einstellung um zusätzlich zum Primärschlüssel weitere Schlüssel
 * zu definieren.
 */
				<UNIQUE>true|false</UNIQUE>

/* Das Feld "INDEX" kann entweder den Wert true, oder false annehmen, wobei false der
 * Defaultwert ist. Ist INDEX=true so wird eine sortierte Liste der Werte dieser Spalte
 * gespeichert, was das Sortieren und Suchen nach den in der Spalte gespeicherten Werten
 * beschleunigen kann.
 */
				<INDEX>true|false</INDEX>

/*
 * Die Anweisungen für die GUI und das SDK können im Feld "DISPLAY" angegeben werden.
 * Dazu existieren jeweils zwei Einstellungen: "HIDDEN" und "READONLY".
 * Wobei "READONLY" bedeutet, dass diese Spalte nicht zum Editieren angezeigt werden soll.
 * Wie der Name schon sagt, bedeutet "HIDDEN", dass die Spalte in der Ausgabe gar nicht
 * auftauchen soll.
 * Es gibt jeweils eine Einstellung, für die Abfragen: "NEW", "EDIT", "VIEW" und "SEARCH".
 * Die Eigenschaften können jeweils global oder für jede Aktion einzeln gesetzt werden.
 */

/* Zunächst die Variante mit globalen Einstellungen
 */
				<DISPLAY>
					<HIDDEN>true|false</HIDDEN>
					<READONLY>true|false</READONLY>
				</DISPLAY>

/* Nun die Variante mit lokalen Einstellungen für jede Option
 */
				<DISPLAY>
					<HIDDEN>
						<NEW>true|false</NEW>
						<EDIT>true|false</EDIT>
						<SELECT>true|false</SELECT>
						<SEARCH>true|false</SEARCH>
					</HIDDEN>
					<READONLY>
						<NEW>true|false</NEW>
						<EDIT>true|false</EDIT>
					</READONLY>
				</DISPLAY>

/*
 * Für den Typ "array" kann die Eigenschaft "display" zusätzlich das Flag "NUMERIC"
 * enthalten, um auszudrücken, dass es sich um ein numerisches Array handelt.
 * Dadurch werden in der grafischen Oberfläche des Programms die Schlüssel nicht
 * angezeigt und bei neuen Einträgen werden die numerischen Schlüssel automatisch
 * vergeben.
 */
				<DISPLAY>
					<NUMERIC>true|false</NUMERIC>
				</DISPLAY>

			</Name der Spalte>


/*
 * Für die Datentypen integer, ip und time kann für das Feld "REQUIRED" der Wert "AUTO"
 * gesetzt werden. Dies bedeutet, dass der Wert automatisch erzeugt wird.
 * Für time    = das aktuelle Datum als Unix-Timestamp
 * Für ip      = die IP des Besuchers
 * Für integer = autoincrement beziehungsweise der Wert einer Sequence
 */
			<Name der Spalte>
				<TYPE>integer|ip|time</TYPE>
				<REQUIRED>AUTO</REQUIRED>
			</Name der Spalte>

/*
 * Für den Datentyp select kann eine Aufzählung der erlaubten Werte angegeben werden.
 *
 * Die Semantik kann man sich relativ leicht merken:
 * + Die GUI stellt Spalten vom Typ select in Formularen als Select-Feld dar.
 * + Die Darstellung im Schema erinnert ebenfalls an ein Select-Formularfeld in HTML.
 */
			<Name der Spalte>
				<TYPE>select</TYPE>
				<DEFAULT>
					<defaultwert>Beschriftung</defaultwert>
					<option 1>Beschriftung 1</option 1>
					<option 2>Beschriftung 2</option 2>
				</DEFAULT>
			</Name der Spalte>

/*
 * Für den Datentyp image können die maximale Dateigröße, Breite und Höhe der Grafik
 * angegeben werden. Ist das Bild zu klein oder zu groß, wird es automatisch
 * auf die angegebene Größe gebracht. Mit dem Wert "Ratio" wird angegeben, ob dabei
 * das Verhältnis von Breite zu Höhe erhalten bleiben soll (true) oder nicht (false).
 * Falls "Ratio" auf "true" gesetzt wird, entsteht eventuell ein Rand um das Bild herum.
 * Deshalb kann eine Hintergrundfarbe angegeben werden.
 * Diese Hintergrundfarbe füllt den unbenutzten Bereich um die Grafik herum aus.
 *
 * Der Formulargenerator kann (wenn er verwendet wird) automatisch ein Upload-Feld
 * erzeugen, mit dem Grafiken an den Server übertragen werden können.
 * Bei einem Upload wird automatisch ein Thumbnail in der Größe 75x75px erzeugt.
 * Der Formulargenerator zeigt beim Aufrufen des Datensatzes automatisch das Thumbnail
 * und einen Link zur vollständigen Grafik an.
 *
 * Grafiken werden aus Gründen der Performance NICHT als Blob in der Datenbank
 * gespeichert, sondern in einem nicht-öffentlichen Verzeichnis im Dateisystem.
 * In der Datenbank wird lediglich der Dateipfad der Grafik hinterlegt.
 * Beim Löschen des Datensatzes (über die Datenbank-API das Frameworks) werden die
 * mit dem Datensatz assoziierte Grafik und das Thumbnail ebenfalls gelöscht.
 */
			<Name der Spalte>
				<TYPE>image</TYPE>
				<LENGTH>max. Upload-Größe in Byte</LENGTH>
				<WIDTH>Breite in Pixel</WIDTH>
				<HEIGHT>Höhe in Pixel</HEIGHT>
				<RATIO>true|false</RATIO>
				<BACKGROUND>
					<0>Zahl 0-255 (rot)</0>
					<1>Zahl 0-255 (grün)</1>
					<2>Zahl 0-255 (blau)</2>
				</BACKGROUND>
			</Name der Spalte>

/*
 * Für die numerischen Datentypen integer und float können zwei
 * weitere Eigenschaften definiert werden.
 *
 * unsigned: die Zahl wird ohne Vorzeichen gespeichert
 * zerofill: beim Darstellen der Zahl werden freie Stellen werden durch '0' aufgefüllt
 *
 * Hinweis: Die Eigenschaft "zerofill" funktioniert nur korrekt, wenn über die Eigenschaft
 * "length" eine feste Länge für die definiert ist.
 */
			<Name der Spalte>
				<TYPE>integer|float</TYPE>
				<UNSIGNED>true|false</UNSIGNED>
				<ZEROFILL>true|false</ZEROFILL>
				<LENGTH>positive integer</LENGTH>
			</Name der Spalte>


		</CONTENT>
	</Name der Tabelle>

/* Hier können weitere Tabellen folgen.
 */

</TABLES>

Betrachten Sie zunächst ein ganz einfaches Beispiel:

/* Der Kopf ist normalerweise immer gleich: */

<USE_STRICT>true</USE_STRICT>
<READONLY>false</READONLY>

/* Danach folgt die Definition der Tabellen der Datenbank */

<TABLES>
	/* hier die Tabelle 'foo' */
	<foo>
		/* Jede Tabelle muss 1 Primärschlüssel haben */
		<PRIMARY_KEY>foo_id</PRIMARY_KEY>
		/* nun folgen die Spalten */
		<CONTENT>
			/* zuerst der Primärschlüssel */
			<foo_id>
				<TYPE>integer</TYPE>
				<LENGTH>8</LENGTH>
			/* REQUIRED=auto erzeugt eine "autoincrement" Spalte */
				<REQUIRED>auto</REQUIRED>
			/* HIDDEN=true macht das Feld für Besucher unsichtbar */
				<DISPLAY>
					<HIDDEN>true</HIDDEN>
				</DISPLAY>
			</foo_id>
			/* jetzt die restlichen Felder */
			<foo_title>
				<TYPE>string</TYPE>
				<LENGTH>128</LENGTH>
				<REQUIRED>true</REQUIRED>
				<DESCRIPTION>Titel</DESCRIPTION>
			</foo_title>
			<foo_text>
				<TYPE>text</TYPE>
				<REQUIRED>false</REQUIRED>
				<DESCRIPTION>Text</DESCRIPTION>
			</foo_text>
		</CONTENT>
	</foo>
	/* eine zweite Tabelle */
	<bar>
		<PRIMARY_KEY>bar_id</PRIMARY_KEY>
		<CONTENT>
			<bar_id>
				<TYPE>string</TYPE>
				<LENGTH>32</LENGTH>
				<REQUIRED>AUTO</REQUIRED>
				<DISPLAY>
					<HIDDEN>true</HIDDEN>
				</DISPLAY>
			</bar_id>
			<bar_value>
				<TYPE>string</TYPE>
				<LENGTH>128</LENGTH>
				<REQUIRED>true</REQUIRED>
				<DESCRIPTION>Wert</DESCRIPTION>
			</bar_value>
			<bar_time>
				<TYPE>time</TYPE>
				<REQUIRED>auto</REQUIRED>
				<DESCRIPTION>Zeit</DESCRIPTION>
			</bar_time>
		</CONTENT>
	</bar>
</TABLES>

Im Folgenden ein Beispiel für eine etwas komplexere Datenbank. Dargestellt ist die Datenstruktur der Gästebuch-Anwendung:

<USE_STRICT>true</USE_STRICT>
<READONLY>false</READONLY>
<TABLES>
	<guestbook>
		<PRIMARY_KEY>guestbook_id</PRIMARY_KEY>
		<CONTENT>
			<guestbook_id>
				<TYPE>integer</TYPE>
				<LENGTH>5</LENGTH>
				<DESCRIPTION>Id (PK)</DESCRIPTION>
				<DISPLAY>
					<HIDDEN>true</HIDDEN>
				</DISPLAY>
			</guestbook_id>
			<profile_id>
				<TYPE>string</TYPE>
				<LENGTH>128</LENGTH>
				<REQUIRED>AUTO</REQUIRED>
				<DESCRIPTION>Id (FK)</DESCRIPTION>
				<DISPLAY>
					<HIDDEN>true</HIDDEN>
				</DISPLAY>
			</profile_id>
			<guestbook_ip>
				<TYPE>ip</TYPE>
				<LENGTH>15</LENGTH>
				<REQUIRED>AUTO</REQUIRED>
				<DISPLAY>
					<HIDDEN>true</HIDDEN>
				</DISPLAY>
			</guestbook_ip>
			<guestbook_name>
				<TYPE>string</TYPE>
				<LENGTH>128</LENGTH>
				<REQUIRED>true</REQUIRED>
				<DESCRIPTION>Name</DESCRIPTION>
			</guestbook_name>
			<guestbook_message>
				<TYPE>text</TYPE>
				<LENGTH>3000</LENGTH>
				<REQUIRED>true</REQUIRED>
				<DESCRIPTION>Text</DESCRIPTION>
			</guestbook_message>
			<guestbook_mail>
				<TYPE>mail</TYPE>
				<LENGTH>255</LENGTH>
				<DESCRIPTION>Mail</DESCRIPTION>
			</guestbook_mail>
			<guestbook_homepage>
				<TYPE>string</TYPE>
				<LENGTH>512</LENGTH>
				<DESCRIPTION>Homepage</DESCRIPTION>
			</guestbook_homepage>
			<guestbook_messenger>
				<DESCRIPTION>Messenger</DESCRIPTION>
				<TYPE>string</TYPE>
				<LENGTH>255</LENGTH>
			</guestbook_messenger>
			<guestbook_msgtyp>
				<DESCRIPTION>Typ</DESCRIPTION>
				<TYPE>select</TYPE>
				<LENGTH>5</LENGTH>
				<DEFAULT>
					<icq>ICQ</icq>
					<aol>AOL</aol>
					<yahoo>Yahoo!</yahoo>
					<msn>MSN</msn>
				</DEFAULT>
			</guestbook_msgtyp>
			<guestbook_opinion>
				<TYPE>select</TYPE>
				<LENGTH>1</LENGTH>
				<CONSTRAINT>
					<INSERT>$VALUE >= 0 && $VALUE <= 5</INSERT>
					<UPDATE>$VALUE >= 0 && $VALUE <= 5</UPDATE>
				</CONSTRAINT>
				<DEFAULT>
					<0>unentschlossen</0>
					<1>sehr gut</1>
					<2>gut</2>
					<3>befriedigend</3>
					<4>ausreichend</4>
					<5>ungenügend</5>
				</DEFAULT>
				<DESCRIPTION>Meinung</DESCRIPTION>
			</guestbook_opinion>
			<guestbook_date>
				<TYPE>time</TYPE>
				<REQUIRED>AUTO</REQUIRED>
				<DESCRIPTION>Datum/Zeit</DESCRIPTION>
				<DISPLAY>
					<HIDDEN>
						<NEW>true</NEW>
                    			</HIDDEN>
				</DISPLAY>
			</guestbook_date>
			<guestbook_comment>
				<TYPE>text</TYPE>
				<LENGTH>1024</LENGTH>
				<REQUIRED>false</REQUIRED>
				<DESCRIPTION>Kommentar</DESCRIPTION>
				<DISPLAY>
					<READONLY>
						<EDIT>true</EDIT>
					</READONLY>
				</DISPLAY>
			</guestbook_comment>
			<guestbook_is_registered>
				<TYPE>integer</TYPE>
				<LENGTH>1</LENGTH>
				<REQUIRED>AUTO</REQUIRED>
				<DEFAULT>0</DEFAULT>
				<DISPLAY>
					<HIDDEN>true</HIDDEN>
				</DISPLAY>
			</guestbook_is_registered>
		</CONTENT>
	</guestbook>
</TABLES>

Wie erstelle ich einen Fremdschlüssel?

Der folgende Code erzeugt zwei Tabellen "foo" und "bar". Die Tabelle "bar" enthält einen Fremdschlüssel auf Tabelle "foo".

<TABLES>

	<foo>

		Primary key constraint:
		<PRIMARY_KEY>foo_id</PRIMARY_KEY>

		<CONTENT>
			<foo_id>
				<TYPE>integer</TYPE>
				<DESCRIPTION>Primärschlüssel der Tabelle foo</DESCRIPTION>
				<REQUIRED>AUTO</REQUIRED>
			</foo_id>
			<foo_name>
				<TYPE>string</TYPE>
				<DESCRIPTION>Eine Spalte, die einen Namen oder Titel enthält</DESCRIPTION>
			</foo_name>
		</CONTENT>
	</foo>

	<bar>

		Primary key constraint:
		<PRIMARY_KEY>bar_id</PRIMARY_KEY>

		Foreign key constraint:
		<FOREIGN_KEYS>

			foo_id = Spaltenname
			foo = Tabellenname

			<foo_id>foo</foo_id>

		</FOREIGN_KEYS>

		<CONTENT>
			<bar_id>
				<TYPE>integer</TYPE>
				<REQUIRED>AUTO</REQUIRED>
				<DESCRIPTION>Primärschlüssel der Tabelle bar</DESCRIPTION>
			</bar_id>
			<foo_id>
				<TYPE>select</TYPE>
				<REQUIRED>true</REQUIRED>
				<DESCRIPTION>Fremdschlüssel auf Tabelle foo, dargestellt als Selectbox</DESCRIPTION>
				<DEFAULT>

					foo_id = Spalte, die in der Datenbank gespeichert wird
					foo_name = Spalte, die im Browser angezeigt wird

					<foo_id>foo_name</foo_id>

				</DEFAULT>
			</foo_id>
		</CONTENT>
	</bar>
</TABLES>

Zusammenhang zwischen Datenbankschemata und der Templatefunktion [%create ...%]

Die Funktion "create" (siehe Abschnitt zu Templates) dient dem Aufruf des Formulargenerators. Der Formulargenerator ist in der Lage, mit den Informationen aus dem Datenbankschema selbstständig Formulare zum Anzeigen, Durchsuchen, Erstellen, Editieren und Löschen von Datensätzen zu generieren. Notwendige Abfragen der Datenbank führt er automatisch aus. In Datenbankschemata wird der Tag "DISPLAY" verwendet, um das Verhalten des Formulargenerators zu steuern. Dieser Tag erlaubt das Ein- oder Ausblenden einzelner Spalten einer Tabelle, abhängig vom Typ des gerade angezeigten Formulars.

Darstellung der Datentypen

Der Formulargenerator zeigt Tabellenspalten abhängig von Ihrem Typ unterschiedlich an. Im Folgenden eine Auflistung der Typen mit Screenshots für die jeweilige Darstellung in der GUI.

Typ der Spalte Darstellung in GUI Beschreibung
integer, float, string Inputfeld Einzeilige Texte und Zahlen werden beim Editieren der Spalte als Inputfeld dargestellt. Ist die Spalte nicht editierbar, wird der Inhalt als Textzeile dargestellt.
boolean Checkbox Eingaben vom Typ "boolean" werden beim Editieren als Checkbox repräsentiert. Beim Anzeigen der Spalte, wird eine Grafik eingefügt, welche den Status des Feldes repräsentiert.
text Textarea Mehrzeilige Texte werden beim Editieren als Textareafelder dargestellt. Ist die Spalte nicht editierbar, wird der Inhalt als Fließtext dargestellt. Bei zu langen Texten werden Scrollbalken erzeugt (CSS: "overflow: auto").
url, ip Inputfeld Der Datentyp "ip" bietet die Möglichkeit, automatisch die IP-Adresse des Besuchers zu speichern. IP-Adressen werden auf Ihre syntaktische Gültigkeit geprüft. In der Regel werden Spalten dieses Typs nicht als editierbar markiert. Falls doch, wird ein Inputfeld angezeigt. Der Datentyp "url" entspricht dem Typ "string", mit dem Unterschied, dass geprüft wird ob die Eingabe eine syntaktisch korrekte URL ist.
mail HTML-Code Beim Editieren wird für diesen Datentyp wird ein Inputfeld angezeigt. Die Eingaben werden syntaktisch auf Gültigkeit geprüft. Eingaben vom Datentyp "mail" werden bei der Darstellung im Browser automatisch verschlüsselt, um Datendiebstahl zu erschweren. Dies gilt grundsätzlich für alle angezeigten Mailadressen. Die Umsetzung erfolgt automatisch in der Darstellungsschicht des Frameworks, Eingriffe von Hand sich daher unnötig.
select Selectbox Der Datentyp "select" ist ein "Aufzählungstyp" (Enumeration). Beim Editieren wird eine Select-Box erzeugt. Der Inhalt der Box kann im Datenbankschema vorgegeben werden (über die Eigenschaft "Default"). Falls das Feld ein Fremdschlüssel ist (d.h. falls auf dieser Spalte ein Foreign-Key Constraint existiert), wird das Menü automatisch mit den Einträgen der verlinkten Tabelle aufgefüllt. Dabei kann angegeben werden, aus welchen Spalten die Beschriftungen und Werte entnommen werden sollen.
set Checkbox Der Datentyp "set" ist eine Variante eines Aufzählungstyps, welcher es gestattet, mehrere Werte auszuwählen (anders als "select", welches nur einen einzigen Wert erlaubt). Beim Editieren wird eine Liste von Checkboxes erzeugt. Werte und Beschriftungen der Boxen können im Datenbankschema vorgegeben (über die Eigenschaft "Default").
time Zeitangabe: Deutsch, Englisch, Russisch Beim Editieren werden für Spalten vom Typ "time" Selectboxen angezeigt, welche die Eingabe erleichtern. Eingaben vom Typ "time" werden automatisch als Timestamp gespeichert und in der GUI als Datum dargestellt. Die Art der Darstellung kann im Administrationsmenü ausgewählt werden und passt sich den gewählten Spracheinstellungen automatisch an. Das Framework stellt das Datum stets automatisch synchron zur Zeitzone des Besuchers und in seiner jeweiligen Landessprache dar.
array Array Eingaben vom Typ "array" können mehrdimensionale Arrays sein. Diese werden beim Editieren als Paare von Schlüsseln und Werten dargestellt. Durch Klick auf "entfernen" wird ein Wert gelöscht, ein Klick auf "neuen Eintrag speichern" fügt einen neuen Wert hinzu. Beim Anzeigen werden die Werte als mehrdimensionale, aufklappbare Baummenüs dargestellt. Beim Überfahren eines Schlüssels mit der Maus, öffnet sich eine Liste der Einträge, welche diesem Schlüssel zugeordnet sind.
array (numerisch) Liste Numerische Listen werden über die Eigenschaft "display.numeric" erzeugt. Sie unterscheiden sich von "normalen" Arrays dadurch, dass keine Felder zur Eingabe des Schlüssels angezeigt werden. Die Vergabe der Schlüssel erfolgt stattdessen automatisch beim Erzeugen eines neuen Eintrags. Beim Anzeigen werden die Werte als Listenelemente dargestellt.
image Uploadfeld Spalten vom Datentyp "image" werden als Thumbnail mit einem Uploadfeld zum Einfügen oder Ersetzen der gespeicherten Grafik dargestellt. Beim Klick auf das Thumbnail wird die vollständige Grafik in einem neuen Fenster geöffnet. Die Grafikdatei wird beim Upload automatisch geprüft und konvertiert. Für die Konvertierung können im Datenbankschema zusätzliche Optionen, wie zum Beispiel die gewünschte Größe, angegeben werden.
file Uploadfeld Der Datentyp "file" dient dem Speichern von Dateien ("binary large objects"). Beim Editieren werden ein Uploadfeld zum Hochladen einer neuen Datei und ein Button für den Download der aktuell gespeicherten Datei angezeigt. Die Dateien selbst verbleiben nach dem Upload aus Gründen der besseren Performance im Dateisystem. Um Speicherplatz zu sparen, werden Sie automatich GZip-komprimiert. Die Komprimierung sorgt außerdem dafür, dass die auf dem Server gespeicherten Dateien nicht ausführbar sind und ein potentieller Angreifer den Upload nicht missbrauchen kann, um Schadcode zu übertragen. Beim Download der Datei wird diese automatisch entpackt, so dass der Nutzer keine Nachteile aus der Komprimierung erfährt und auch kein Dekomprimierungsprogramm installiert haben muss. Um trotzdem einen schnelleren Download zu gewährleisten, werden die Daten, falls der Browser des Nutzers diese Funktionalität anbietet, automatisch als komprimierter Datenstrom übertragen. Der Browser übernimmt das Entpacken selbstständig. Ein Eingreifen von Hand ist nicht erforderlich. Die Steuerung dieses Features übernimmt das Framework selbstständig und vollautomatisch.

Gegenüberstellung von Datentypen und deren Darstellung durch den Formulargenerator

besondere Konfiguration der Datentypen "image" und "file"

Das Downloaden von Dateien oder Öffnen von Grafiken bei Spalten vom Datentyp "image" oder "file", wird über die Aktion "download_file" realisiert, welche Sie im Plugin "default_library" finden. Dies geschieht normalerweise automatisch.

Aus Sicherheitsgründen ist der Zugriff auf diese Aktion per Voreinstellung auf Nutzer der Nutzergruppe "Admin" beschränkt. Dies ist die Nutzergruppe mit dem höchsten Sicherheitslevel. Wenn Sie auch Nutzern mit einem geringeren Sicherheitslevel Zugriff auf diese Daten gestatten wollen, müssen Sie die Sicherheitsbeschränkung dieser Aktion herabsetzen.

Um dies zu tun, editieren Sie bitte die Datei "plugins/default_library.config" in einem Texteditor Ihrer Wahl. Suchen Sie in dieser Datei den folgenden Abschnitt.

<DOWNLOAD_FILE>
    <TYPE>primary</TYPE>
    <MODE>1</MODE>
    <TEMPLATE>NULL</TEMPLATE>
    <PERMISSION>100</PERMISSION>
</DOWNLOAD_FILE>

Der Sicherheitslevel wird dargestellt als Zahl zwischen 0 und 100, wobei 100 der Gruppe "Admin" und 0 der Gruppe "Guest" entspricht. Ändern Sie den Wert "100" auf eine Zahl, die Ihnen angemessen erscheint.

Einige Vorschläge finden Sie in der folgenden Tabelle:

Nutzergruppe Sicherheitslevel
Gast (guest) 0
registrierter Nutzer (registered) 1
Moderator (mod) 30
Besitzer (owner) 75
Administrator (admin) 100

Gegenüberstellung von Nutzergruppe und Sicherheitslevel

In diesem Beispiel wurde der Wert auf "1" geändert.

<DOWNLOAD_FILE>
    <TYPE>primary</TYPE>
    <MODE>1</MODE>
    <TEMPLATE>NULL</TEMPLATE>
    <PERMISSION>1</PERMISSION>
</DOWNLOAD_FILE>

Speichern Sie anschließend die Datei.

Damit die Änderungen wirksam werden, müssen Sie im Administrationsmenü des Yana Frameworks den Plugin-Cache aktualisieren.

Screenshot
Abbildung: Schaltfläche zum Aktualisieren des Plugin-Cache

Nach Klick auf die Schaltfläche werden die geänderten Einstellungen sofort wirksam.

Dateisystem

Wie erhalte ich den Inhalt von Verzeichnissen?

Die Funktion dirlist() liefert für ein Verzeichnis eine sortierte Liste der enthaltenen Dateien und Verzeichnisse als numerisches Datenfeld zurück. Die obligatorischen Verzeichniseinträge "." und ".." werden nicht aufgelistet. Dateien, deren Dateinamen mit dem Zeichen "." beginnen werden ebenfalls nicht aufgelistet. Das betrifft insbesondere Dateinamen wie ".htaccess" oder ".password". Die Dateinamen enthalten keine Pfadangaben. Verzeichnisnamen enthalten keinen abschließenden Querstrich "/".

Der optionale Parameter $filter kann verwendet werden um die Ausgabe auf bestimmte Dateiendungen zu beschränken. Wildcards sind nicht gestattet. Der Dateifilter darf lediglich alphanumerische Zeichen, sowie die Zeichen '.', '-' und '_' enthalten. Andere Zeichen werden beim Aufruf der Funktion automatisch entfernt.

alle Einträge eines Verzeichnisses ausgeben:
<?php
echo implode("<br>", dirlist("foo/"));
?>

Ausgabe:

foo1.foo2
foo3.foo2
foo4.foo5
foo6.foo7

alle Einträge mit passender Dateiendung ausgeben:
<?php
echo implode("<br>", dirlist('foo/', '*.foo2'));
?>

Ausgabe:

foo1.foo2
foo3.foo2


... mit mehreren Dateiendungen:

<?php
echo implode("<br>", dirlist('foo/', '*.foo2|*.foo5'));
?>

Ausgabe:

foo1.foo2
foo3.foo2
foo4.foo5

objektorientierte Variante:

<?php
$dirStream = new DirStream("foo/");
$dirStream->read();
$dirlist = $dirStream->dirlist('*.foo2|*.foo5');
echo implode("<br>", $dirlist);

/* Hinweis: das Setzen des Dateifilters ist permanent. */

$dirStream->dirlist('*.foo2|*.foo5');
echo $dirStream->length();
/* Ausgabe: 2 */

echo count($dirStream->get());
/* Ausgabe: 2 */

/* Ein erneuter Aufruf von dirlist() setzt den Dateifilter neu */
$dirStream->dirlist("");
echo $dirStream->length();
/* Ausgabe: 4 */
?>

Wie kann ich Verzeichnisse anlegen oder löschen?

Die Funktionen $dirStream->create($mode) beziehungsweise $dirStream->delete() sind für Erzeugen beziehungsweise Löschen von Verzeichnissen verantwortlich. Der optionale Parameter $mode kann verwendet werden, um unter LINUX/UNIX -Betriebssystemen Zugriffsrechte von Verzeichnissen festzulegen. Der Defaultwert ist 777.

Beispiele für gültige Werte für $mode finden Sie in der folgenden Tabelle. Dabei steht "r" für "readable", "w" für "writeable" und "x" für "executable".

Besitzer Gruppe sonstige Nutzer Wert

rwx

rwx

rwx

777

rw-

rw-

---

660

rw-

rw-

rw-

666

rwx

r-x

r-x

755

rwx

r-x

---

750

rwx

---

---

700

Beispiele für gültige Werte (entsprechend Unix: CHMOD)

<?php
$dirStream = new DirStream("foo/");
$dirStream->read();

/* erzeuge das Verzeichnis "foo/" */
$dirStream->create();

/* erzeuge das Verzeichnis "foo/" mit Zugriffsrechten 660 */
$dirStream->create(660);

/* Anzahl der Dateien in einem Verzeichnis feststellen */
print "Verzeichnis 'foo/' enthält ".$dirStream->length()." Dateien.";

/* lösche das Verzeichnis "foo/" */
$dirStream->delete();

/* lösche das Verzeichnis "foo/" inklusive aller Dateien und Unterverzeichnisse */
$dirStream->delete(true);

/* prüfe ob Verzeichnis existiert */
$test = $dirStream->exists();
if ($test === true) {
	print "Verzeichnis existiert";
} else if ($test === false) {
	print "Verzeichnis existiert NICHT";
}
?>

Wie lese ich den Inhalt einer Config- oder SML-Datei?

Die Funktion SML::getFile() lädt die angegebene Konfigurationsdatei im SML-Format und liefert den Inhalt als PHP-Variable zurück.

<?php
/* Lies Inhalte von Datei und gib Inhalte als Array zurück */
$array = SML::getFile("foo.config");

/* Schlüssel in Großbuchstaben */
$array = SML::getFile("foo.config", CASE_UPPER);

/* Schlüssel in kleinen Buchstaben */
$array = SML::getFile("foo.config", CASE_LOWER);

/* Schlüssel so wie gespeichert (default) */
$array = SML::getFile("foo.config", CASE_MIXED);

/* ... oder: */
$array = SML::getFile(file("foo.config"));

/* ... oder: */
$array = SML::decode(file_get_contents("foo.config"));

/* einen SML-String erzeugen und dekodieren */
$input_array  = array(1,2,3,array(4,5),'a'=>6,'B'=>7);
$output_array = SML::decode(SML::encode($input_array));
$input_array == $output_array; // true

/* objektorientierte Variante, gemischte Schreibweise */
$configFile = new ConfigFile("foo.config");
$configFile->read();
$array = $configFile->get();

/* objektorientierte Variante, Schlüssel in Großbuchstaben */
$smlFile = new SML("foo.config");
$smlFile->read();
$array = $smlFile->get();
?>

Navigieren innerhalb einer SML-Datei:

Angenommen die Datei "foo.config" hätte folgenden Inhalt:

<ROOT>
	<FOO1>
		<FOO2>text</FOO2>
		<FOO3>
			<0>1</0>
			<1>foo</1>
		</FOO3>
	</FOO1>
</ROOT>

<?php
$mixed = $smlFile->get("ROOT.FOO1");
print_r($mixed);
?>

Diese Abfrage liefert den Teilbaum ROOT.FOO1 mit FOO1 als Wurzelement.

Ausgabe:

array(
	"FOO2" => "text",
	"FOO3" => array (
		0 => 1,
		1 => "foo"
	)
)

Wie schreibe ich eine Variable in eine Config- oder SML-Datei?

Die Funktion SML::encode() erzeugt für die übergebene Variable eine Darstellung als SML-Code und liefert diesen als String zurück. Es muss sich entweder um eine Variable mit einem skalaren Wert oder ein Array handeln.

Bitte beachten Sie: die Funktion "SML::encode" erkennt keine unendlichen Rekursionen. Daher müssen die Datenfelder rekursionsfrei sein. Andernfalls wird durch den Compiler eine Fehlermeldung erzeugt.

Speichert die Einträge eines Array in der Datei "foo.config":

<?php
$string = SML::encode($array, "ROOT");
file_put_contents("foo.sml", $string);
?>

Ersetzen Sie "ROOT" durch den Namen des Wurzelelements!

Benutzen von Großbuchstaben, Kleinbuchstaben und gemischter Schreibweise analog zu SML::decode():

<?php
$string = SML::encode($array, "ROOT", CASE_UPPER); // groß
$string = SML::encode($array, "ROOT", CASE_LOWER); // klein
$string = SML::encode($array, "ROOT", CASE_MIXED); // gemischt (default)
?>

objektorientierte Variante, gemischte Schreibweise:

<?php
$configFile = new SML("foo.sml");
$configFile->read();
$configFile->create();
$configFile->insert($string);
$configFile->write();
?>

objektorientierte Variante, Schlüssel in Großbuchstaben:

<?php
$smlFile = new SML("foo.sml", CASE_UPPER);
$smlFile->read();
$smlFile->create();
$smlFile->insert($string);
$smlFile->write();
?>

Wie kopiere ich eine Datei?

Zum Kopieren einer Datei besitzen alle YANA-Klassen, die Dateien repräsentieren, die Funktion "copy". Beim Kopieren der Datei können außerdem auch deren Zugriffsrechte gesetzt werden. Sollte das Verzeichnis, in welches die Datei kopiert werden soll, noch nicht existieren, kann es automatisch erzeugt werden. Letzteres ist optional.

Im Folgenden einige Beispiele.

eine Datei kopieren:

<?php
$foo = new SecureFileStream("foo.txt");
$foo->copy("bar.txt");

$foo->copy("bar.txt"); // Fehlermeldung: Datei existiert bereits
?>

eine Datei kopieren und bereits existierende Dateien überschreiben:

<?php
$foo->copy("bar.txt", true);

$foo->copy("bar/foo2.txt"); // Fehlermeldung: Verzeichnis 'bar' existiert nicht
?>

eine Datei kopieren und fehlende Verzeichnisse automatisch erzeugen:

<?php
$foo->copy("bar/foo2.txt", false, true);

/* Das Verzeichnis 'bar/' wurde angelegt und die Datei 'foo2.txt' darin gespeichert.
   Die Zugriffsrechte für das Verzeichnis wurden per Default auf 766 gesetzt. */

/* das Verzeichnis wird nun wieder gelöscht */
$dir = new DirStream("bar");
$dir->delete(true);
?>

eine Datei kopieren und Zugriffsrechte für die kopierte Datei auf 655 setzen:

<?php
$foo->copy("bar/foo2.txt", false, false, 655);

/* Das Verzeichnis 'bar/' wurde erneut angelegt.
   Die Zugriffsrechte für das Verzeichnis wurden nun auf 655 gesetzt - so wie für
   die Datei. */
?>

Besucherzähler und Statistiken

Wie erstelle ich einen Zähler?

Das Framework bietet die Möglichkeit persistente Zählervariablen, also solche deren Wert automatisch gespeichert wird, zu verwenden.

Es gibt zwei Arten von Zählervariablen: solche, die mit IP-Check, welche nur dann zählen, wenn der Nutzer mit der aktuellen IP nicht innerhalb der letzten 3 Stunden eine Veränderung des Zählers bewirkt hat. Und solche ohne IP-Check, welche stets weiter zählen wenn Sie aufgerufen werden.

Im Folgenden einige Beispiele.

<?php
/* Erzeuge einen Zähler mit IP-Check */
$counter = new Counter("meine_statistiken", YANA_COUNTER_USE_IP);
/* ... oder auch: */
$counter = new Counter("meine_statistiken");

/* Erzeuge einen Zähler ohne IP-Check */
$counter = new Counter("meine_statistiken", YANA_COUNTER_IGNORE_IP);

/* Den Zähler "test1" um 1 erhöhen */
$counter->count("test1");
/* Den Zähler "test2" um 1 erhöhen und eine Beschreibung der Änderung speichern */
$counter->count("test2", "Bewertung");

/* Den Zähler "test1" um 3 erhöhen */
$counter->count("test1", "Bewertung", 3);

/* Den Zähler "test1" um 2 verringern */
$counter->count("test1", "Bewertung", -2);
?>

Wie frage ich den Zählerstand ab?

<?php
$counter = new Counter("meine_statistiken");

/* Den Zählerstand von "test1" abfragen */
$int = $counter->getCount("test1");

/* Die Beschreibung von Zähler "test1" abfragen */
$string = $counter->getInfo("test1");

print $string.":\t".$int;
/*
  Ausgabe
  Bewertung: 2
*/

/* Alle Zähler abfragen */
$array = $counter->getCount("*");
foreach ($array as $a => $b)
{
    print $a.":\t".$b;
}
?>

Wie erzeuge ich einen grafischen Besucherzähler?

<!-- In der Template-Datei fügen Sie folgendes ein: -->
<img src=[%"action=graphic_counter&target=0"|href%]>

Mit dem Parameter "target" wählen Sie die Grafik aus. Gültige Werte sind die Zahlen 0-6.

Wert für Target Darstellung
0
1
2
3
4
5
6

E-Mails versenden

Versionsinformation: Die Funktionen send_mail und form_mail, sowie die Klasse form_mailer wurden in Version 2.8 umbenannt in sendMail, formMail und formMailer, um der Namenskonvention des Frameworks zu entsprechen. Die Funktion sendMail ist ab Version 2.8 eine statische Funktion der Klasse Mailer. Die Funktion formMail ist ab Version 2.8 eine statische Funktion der Klasse FormMailer.

Allgemeines zum Versand von Mails

Das Framework bietet die Funktion Mailer::mail() zum Versand von Mails. Diese Funktion implementiert eine Reihe von Sicherheitsvorkehrungen, zum Schutz vor verschiedenen Arten von Header-Injection.

Die Funktion "Mailer::mail" ist eine gegen Missbrauch und "Header-Injection" abgesicherte Variante der nativen PHP-Funktion "mail". Anders als "mail" werden alle Eingabedaten geprüft und auch nicht alle Header-Informationen, welche "mail" prinzipiell gestattet sind erlaubt.

Es wird "true" zurückgegeben, wenn die Mail versandt werden konnte, "false" sonst. Der Wert "true" bedeutet jedoch nicht, dass die Mail erfolgreich zugestellt wurde. Er bedeutet lediglich, dass die Eingabedaten im Sinne dieser Funktion syntaktisch korrekt waren.

Die Funktion erzeugt im Header der Mail die zusätzlichen Einträge "x-yana-php-header-protection" und "x-yana-php-spam-protection".

Wenn Sie eine Mail empfangen, die über YANA versendet wurde, können Sie im Header der Mail die entsprechenden Einträge prüfen, um zu sehen ob das Framework im Nachrichtentext Unregelmäßigkeiten entdeckt hat.

bool Mailer::mail(string $recipient, string $subject, string $text [, array $header ] )

Aus Sicherheitsgründen gelten folgende Einschränkungen.

Die Liste der von Header akzeptierten Parameter lautet
Parameter Typ Default Beschreibung
from mail - Eine gültige Mailadresse
return-path mail - Eine gültige Mailadresse
cc mixed - Entweder eine gültige Mailadresse oder ein numerisches Datenfeld mit mehreren Mailadressen. An alle angegebenen Adressen wird eine Kopie der Nachricht versandt. Anders als bei "bcc" ist die Liste der Empfänger jedoch für alle Empfänger sichtbar.
content-type string text/plain;
charset="UTF-8"
Bestimmt den MIME-Type der Nachricht. Nur MIME-Type und Charset sind als Eingaben erlaubt. Andere Werte werden ignoriert.
mime-version float 1.0 Angabe muss entsprechend folgendes regulären Ausdrucks erfolgen (Perl-Syntax): /^\d\.\d$/
content-transfer-encoding string - Angabe muss entsprechend folgendes regulären Ausdrucks erfolgen (Perl-Syntax): /^\d{,2}bit$/i

gültige Belegungen für den Parameter $header der Funktion Mailer::mail()

Die Verwendung von "BCC" ist aus Sicherheitsgründen nicht gestattet.

Wie sende ich einen Text als Mail?

<?php
$recipient = "meineMail@domain.tld";
$subject = "Benachrichtigung";

$mailer = new Mailer("skins/mein_skin/beispiel.mail");
$mailer->subject = $subject;
$mailer->sender  = $ARGS["mail"];
$mailer->insert("NAME", $ARGS["name"]);
$mailer->insert("NACHRICHT", $ARGS["nachricht"]);
$mailer->insert("IP", $_SERVER["REMOTE_ADDR"]);
$test = $mailer->send($recipient);

if ($test === true) {
    print "Versand erfolgreich";
} else if ($test === false) {
    print "Versand nicht erfolgreich";
}
?>

Wie sende ich eine Mail auf Basis eines Templates?

Das Template "beispiel.mail" könnte wie folgt aussehen:

Hallo [%$NAME%]!

Jemand hat dir eine Nachricht hinterlassen, sie lautet:

[%$NACHRICHT%]

IP des Besuchers: [%$IP%]

Dies ist der Quelltext zum Versenden der Mail:
<?php
$recipient = "meineMail@domain.tld";
$subject = "Benachrichtigung";

$mailer = new Mailer("skins/mein_skin/beispiel.mail");
$mailer->subject = $subject;
$mailer->sender  = $ARGS["mail"];
$mailer->insert("NAME", $ARGS["name"]);
$mailer->insert("NACHRICHT", $ARGS["nachricht"]);
$mailer->insert("IP", $_SERVER["REMOTE_ADDR"]);
$test = $mailer->send($recipient);

if ($test === true) {
    print "Versand erfolgreich";
} else if ($test === false) {
    print "Versand nicht erfolgreich";
}
?>
Eine versandte Mail könnte dann wie folgt aussehen:

Hallo Thomas!

Jemand hat dir eine Nachricht hinterlassen, sie lautet:

Hallo Welt

IP des Besuchers: 127.0.0.1

Anmerkung: vor dem Versand der E-Mail prüft die Funktion $mailer->send() die Eingabedaten automatisch auf Versuche von Header-Injection und säubert alle Eingaben. Es kann jedoch absolut nichts schaden, wenn Sie die Syntax der Eingabedaten trotzdem auch in Ihrem Skript noch einmal überprüfen bevor Sie die Funktion aufrufen.

Wie versende ich Daten aus einem Formular als Mail?

Dies ist der Quelltext zum Versenden der Mail:
<?php
$formMailer = new FormMailer();
// Betreff
$formMailer->subject = "Benachrichtigung";
// Kopf- und Fusszeile
$formMailer->headline = "Inhalte des Kontaktformulars:\n\n"
$formMailer->footline = "\n\nYANA formmailer at ".$_SERVER['SERVER_NAME'];
// Formularinhalt
$formMailer->content = $_POST;

$test = $formMailer->send("meineMail@domain.tld");

if ($test === true) {
    print "Versand erfolgreich";
} else if ($test === false) {
    print "Versand nicht erfolgreich";
}
?>
Eine versandte Mail könnte dann wie folgt aussehen:

Inhalte des Kontaktformulars:

==========================================
  Benachrichtigung
==========================================

    name:      Walter
    alter:     35
    betreff:   Neueintrag
    dringend:  [x]
    nachricht: Bitte Passwort senden!

==========================================
Datum: 11.08.2006 10:06:41
IP: 127.0.0.1

YANA formmailer at foo.server.tld

Formulardaten prüfen

Wie kann ich Nutzereingaben vor der Verarbeitung säubern?

Zu diesem Zweck bietet Ihnen YANA die Funktion untaintInput().

Die Funktion verfügt über folgende Parameter:

Parameter

Typ

Default

Beschreibung

value mixed - zu säuberndes Datum
type string - Datentyp

Neben den von PHP unterstützten nativen Typen sind noch folgende Werte erlaubt:
  • time: UTC-Zeitcode (Typ Integer, Länge 11)
  • ip: IP-Adresse (Typ String, Länge 15)
  • mail: Mailadresse (Typ String)
  • select: wird behandelt wie "string"
  • text: wird behandelt wie "string"
length integer 0 Maximale Länge des Datums
escape integer 0 siehe Tabelle

Parameterliste untaintInput

Der Parameter $escape kann mit einer der folgenden Konstanten belegt werden.

Bezeichner Beschreibung
YANA_ESCAPE_NONE keine Änderungen durchführen (Default)
YANA_ESCAPE_SLASHED wandelt einfache und doppelte Anführungszeichen in ihre entsprechenden Escapesequenzen in C-Syntax um
YANA_ESCAPE_TOKEN ersetzt enthaltene Token durch ihre HTML-Entities
YANA_ESCAPE_CODED ersetzt HTML-Symbole, beispielsweise Tagklammern, durch Entities
YANA_ESCAPE_LINEBREAK wandelt alle Whitespace-Zeichen (insbesondere Zeilenumbrüche) in Leerzeichen um
YANA_ESCAPE_USERTEXT zur Behandlung von Text aus Textarea-Feldern

Gültige Belegungen für den Parameter $escape der Funktion untaintInput

Für INPUT-Felder sollten Sie stets die Funktion untaintInput() mit dem Parameter YANA_ESCAPE_LINEBREAK aufrufen. Das verhindert, dass ein Angreifer Zeilenumbrüche in Ihre Ausgabe schmuggelt. Für TEXTAREA-Felder sollten Sie den Parameter YANA_ESCAPE_USERTEXT verwenden. Dieser verhindert viele Formen von Flooding, indem Zeichenfolgen die sich ständig wiederholen (Copy'n'Paste Flooding) entfernt werden, oder zum Beispiel ellenlange Texte oder Leerzeichen nach einer bestimmten Anzahl von Leerzeichen per Zwang umgebrochen werden, um das Layout Ihrer Seite nicht zu zerstören.

Logging und Fehlermeldungen

Wo finde ich die Log-Daten?

YANA schreibt alle Log-Einträge in eine Tabelle der Datenbank. Dies geschieht jedoch nur, wenn Logging aktiviert ist. Sie können dies deaktivieren, um Speicherplatz zu sparen. Dieses Feature ist nach der Installation per Default deaktiviert.

Wie aktiviere ich Logging?

Wie erstelle ich einen Log-Eintrag?

<?php
global $YANA;

/* Einen Text in die Logs schreiben */
$log = new Log("Mein Log-Eintrag");
$YANA->report($log);

/* Text und Dump von Daten */
$dump = $irgendwelche_daten;
$log  = new Log("Mein Log-Eintrag",$dump);
$YANA->report($log);

/* den erzeugten Log-Eintrag ansehen */
print $log->getLog();
?>

Wie erzeuge ich eine Fehlermeldung?

Fehlermeldung erzeugen

Durch Aufruf von $YANA->report(Report $report) kann eine Textmeldung erzeugt werden.

Der Parameter $report ist eine Instanz einer der folgenden Klassen. Diese Klassen haben die gemeinsame Oberklasse "Report".

Klasse Beschreibung
Log für Ausgabe in Log-Datei
Message Erfolgsmeldung (Bildschirm)
Warning Warnung
Alert Hinweis
Error Fehler

akzeptierte Typen für Parameter $report

Der Konstruktor wird wie folgt aufgerufen:

new Log(string $text [, mixed $data]);

Das folgende Beispiel schreibt eine Meldung in die Log-Datei und erzeugt dann einen Text für die Ausgabe am Bildschirm.

$YANA->report( new Log("IO-ERROR: Unable to read file $a") );
$YANA->report( new Error('NOT_READABLE', array('FILE' => $a) ) );

Verwendung

Der Parameter $text kann ein Error-Code sein, oder auch ein beliebiger Fließtext. Für Bildschirmausgabe sollten Error-Codes verwendet werden. Für Ausgaben in die Log-Datei bietet sich englischer Fließtext an. Der Parameter $data ist optional und enthält weitere Optionen. Beispielsweise den Datensatz, der nicht gespeichert werden konnte, oder den Namen einer Datei, die gerade nicht geöffnet werden kann.

Gültige Error-Codes für den Parameter $text sind unter anderem (AUSZUG):

Code Beschreibung Textauszug
200 Erfolg Änderungen wurden gespeichert. Vielen Dank !!!
500 Allgemeiner Fehler Es ist ein Fehler aufgetreten...
403 Fehler: Zugriff verweigert Passwort erforderlich. Sie betreten einen geschützten Bereich...
INPUT_INVALID Fehler: Falsche Eingabe Ein gewählter Parameter ist ungültig...
404 Fehler: Datei nicht gefunden Bitte überprüfen Sie die angegebene URL und versuchen Sie es erneut.
ALLREADY_EXISTS Fehler: Eintrag doppelt Es konnte kein neuer Eintrag mit der id "%ID%" erzeugt werden, weil bereits ein anderes Eintrag mit diesem Namen existiert.
FILE_NOT_CREATED Fehler: IO-Error Die Datei "%FILE%" konnte nicht erzeugt werden.
NOT_WRITEABLE Fehler: IO-Error Der Schreibzugriff auf die Ressource "%FILE%" ist gescheitert. Daten konnten nicht gespeichert werden.
NOT_READABLE Fehler: IO-Error Der Zugriff auf die Ressource "%FILE%" ist gescheitert. Daten konnten nicht gelesen werden.

akzeptierte Belegungen für Parameter $text

Enthaltene Token, wie %FILE% werden ersetzt in der folgenden Weise:

<?php
$YANA->report( new Warning('FILE_NOT_CREATED', array('FILE' => $a)) );
?>

Das besondere an $YANA->report() ist, dass Sie damit gleichzeitig Textmeldungen in die Log-Datei schreiben UND Meldungen am Bildschirm ausgeben können. Wird die Methode mehrmals aufgerufen, werden mehrere Textmeldungen erzeugt.

<?php
$YANA->report( new Warning('FILE_NOT_CREATED', array('FILE' => $a)) );
/* ... */
$YANA->report( new Alert('NOT_WRITEABLE', array('FILE' => $a)) );
/* ... */
$YANA->report( new Error('500') );
$YANA->report( new Log("Input/Output Error in File $a.", $lost_data) );
return false;
?>

Der Aufruf von Yana->report erzeugt nur die Textmeldung, bricht aber das Programm nicht ab. Um das Programm zu unterbrechen, verwenden Sie die Methode Yana->exitTo. Bitte beachten Sie: verwenden Sie NICHT die PHP-Methoden exit() oder die(). Andernfalls wird keine Ausgabe erzeugt.

Das Programm unterbrechen

Die Methode Yana->exitTo( [string $action] ) kann verwendet werden um das Programm zu unterbrechen und anzugeben, welche Aktion anschließend ausgeführt werden soll. Das heißt, die Verarbeitung der aktuellen Aktion wird abgebrochen und stattdessen wird das Skript mit der Aktion $action fortgesetzt.

Dabei gibt das Framework alle Textmeldungen an den Browser aus und ruft sich selbst erneut auf. Der Parameter $action entspricht dabei dem URL-Parameter "action".

Wenn der Parameter $action nicht angegeben wird, dann wird stattdessen automatisch die Startseite aufgerufen.

Sie können für $action die spezielle Aktion "null" verwenden, falls Sie das Programm beenden möchten OHNE dass mit der Verarbeitung einer anderen Aktion fortgesetzt werden soll.

Im Folgenden ein einfaches Beispiel:

<?php
// erzeuge einige Textmeldungen
$YANA->report( new Log('Ein Eintrag für die Log-Files') );
$YANA->report( new Alert('NOT_WRITEABLE', array('FILE' => $a)) );
// stoppe die Bearbeitung des Programms und setze es mit der Aktion 'index' fort
$YANA->exitTo('index');

// erzeuge eine Fehlermeldung
$YANA->report( new Error('Access denied!') );
// Abbruch des Programm (setze NICHT mit anderer Aktion fort)
$YANA->exitTo('null');

// Abbruch des Programms und Aufruf der Startseite
$YANA->exitTo();
?>

Profilvariablen lesen und schreiben

Allgemeines zum Verständnis

YANA stellt einen globalen Speicherbereich zur Verfügung, der von allen Plugins gelesen und verändert werden kann. Alle Variablen, die in diesem Bereich gespeichert werden, stehen Ihnen automatisch in allen Skins und Templates für die Ausgabe zur Verfügung. Bitte beachten Sie: der globale Speicherbereich in YANA ist etwas anderes als der global Namespace von PHP.

Innerhalb dieses Speichers werden Werte als ein Baum, in Form von mehrdimensionalen, assoziativen Arrays gespeichert. Der Zugriff auf diesen Speicherbereich erfolgt analog zu Smarty – oder, falls Ihnen der Vergleich besser gefällt, ähnlich wie mit XPath – über einen Schlüssel.

Zum Beispiel:

Angenommen der Baum sieht wie folgt aus:

array(
    "a" => 2,
    "b" => array(
        "c" => 3,
         1  => 4
        )
);

Dann können Sie folgende Schlüssel verwenden:
<?php
$array = $YANA->getVar("*"); // mit Hilfe des Schlüssels "*" erhalten Sie eine Kopie des gesamten Arrays
$int = $YANA->getVar("a");   // Ausgabe: 2
$array = $YANA->getVar("b"); // Ausgabe: array("c" => 3, 1 => 4)
$int = $YANA->getVar("b.c"); // Ausgabe: 3

/* Anders als in XML-Dateien sind hier numerische Ids erlaubt: */
$int = $YANA->getVar("b.1"); // Ausgabe: 4
?>

Wie kann ich Variablen aus dem globalen Speicher lesen?

Die Funktion $YANA->getVar() erlaubt Ihnen das Lesen von Werten im globalen Speicherbereich.

<?php
global $YANA;

/* alle Werte lesen */
$array = $YANA->getVar("*");

/* einzelne Werte lesen */
$mixed = $YANA->getVar("FOO1.FOO2.FOO3");

/* alternativ */
$mixed = $YANA->registry->getVar("FOO1.FOO2.FOO3");
?>

Wie kann ich Variablen im globalen Speicher schreiben?

Die Funktion $YANA->setVar() erlaubt Ihnen das Schreiben von Werten in den globalen Speicherbereich.

<?php
global $YANA;

/* Variable "MEINE_VARIABLE" registrieren */
$bool = $YANA->setVar("MEINE_VARIABLE", $neuer_wert);

$bool = $YANA->setVar("FOO1.FOO2.MEINE_VARIABLE", $neuer_wert);

/* alternativ */
$mixed = $YANA->registry->setVar("FOO1.FOO2.MEINE_VARIABLE", $neuer_wert);
?>

Wie kann ich Variablen im globalen Speicher löschen?

Dazu bietet YANA die Funktion $YANA->unsetVar(). Ein Beispiel:

<?php
global $YANA;

/* Variable "MEINE_VARIABLE" löschen */
$bool = $YANA->unsetVar("MEINE_VARIABLE");

$bool = $YANA->unsetVar("FOO1.FOO2.MEINE_VARIABLE");

/* alternativ */
$mixed = $YANA->registry->unsetVar("FOO1.FOO2.MEINE_VARIABLE");
?>

Wie kann ich den Typ einer Variablen im globalen Speicher ändern?

Dazu bietet YANA die Funktion $YANA->setType(). Ein Beispiel:

<?php
global $YANA;

/* den Typ der Variable "MEINE_VARIABLE" auf String ändern */
$bool = $YANA->setType("MEINE_VARIABLE", "string");

$bool = $YANA->setType("FOO1.FOO2.MEINE_VARIABLE", "string");

/* alternativ */
$mixed = $YANA->registry->setType("FOO1.FOO2.MEINE_VARIABLE", "string");
?>

Welche interessanten Daten liegen im globalen Speicher?

Liste der installierten Plugins
Eine Liste der installierten Plugins ausgeben:
<?php
global $YANA;

$array = $YANA->getVar("INSTALLED_PLUGINS");
print_r($array);
?>
Ausgabe:
    Array
        (
            [CONFIG] => 1
            [DB_ADMIN] => 1
            [DEFAULT_LIBRARY] => 1
            [GUESTBOOK] => 1
            [GUESTBOOK_ADMIN] => 1
            [USER] => 1
        )
Prüfen ob ein bestimmtes Plugin installiert ist:
<?php
$bool = $YANA->getVar("INSTALLED_PLUGINS.MEIN_PLUGIN");
if ($bool) {
    print "Plugin 'MEIN_PLUGIN' gefunden.";
} else {
    print "Plugin 'MEIN_PLUGIN' nicht gefunden.";
}

/* alternativ */
$YANA->plugins->isInstalled('MEIN_PLUGIN');
?>
aktuelle Profileinstellungen

Das "Website-Profil" wird über den URL-Parameter "id" ausgewählt. Jedes Profil kann individuelle Einstellungen haben. Diese Einstellungen werden ebenfalls im globalen Speicherbereich des Frameworks abgelegt. Wird kein Profil gewählt, dann wird das Profil "default" verwendet. De facto müssen Sie als Programmierer sich nicht darum kümmern, welches Profil gewählt ist. Sie müssen nur wissen, dass in den Profildaten Einstellungen, wie die gewählte Hintergrundfarbe der Seite, die bevorzugte Schriftart und andere interessante Daten gespeichert sind, auf die Sie bei Bedarf zugreifen können.

<?php
global $YANA;

/* die aktuellen Profileinstellungen lesen und ausgeben */
$array = $YANA->getVar("PROFILE");
print_r($array);
?>

Ausgabe:
Array
(

>> Layout der Website

    [BGCOLOR] => #F0F0F0
    [PFONT] => Arial, Helvetica, sans-serif
    [BGIMAGE] =>
    [LOGO] =>
    [HSIZE] =>
    [HCOLOR] =>
    [HFONT] =>
    [PSIZE] =>
    [PCOLOR] =>

>> Gewählte Sprache, Skin und Verzeichnis für Emoticons / Smilies

    [LANGUAGE] => deutsch.config
    [SKIN] => default.config
    [SMILEYDIR] => common_files/smilies/

>> Sonstige Einstellungen

    [USERMODE] => 1
    [AUTO] => 1
    [TIMEFORMAT] => 0

>> Protokollierung

    [LOGGING] => 1
    [LOG_LENGTH] => 50

>> Einstellungen für Plugin "rss to html factory"

    [RSS] => Array
        (
            [FILE] => plugins/rss/test.rss
            [MAX] => 5
        )

>> Einstellungen für Plugin "guestbook" (Gästebuch)

    [GUESTBOOK] => Array
        (
            [NOREPLY] => noReply@meineAdresse.tld
            [FLOODING] => 0
            [ENTPERPAGE] => 5
            [NOTIFICATION] =>
            [SENDMAIL] =>
            [MAIL] => meinName@meineAdresse.tld
            [FILE] =>
            [SPAMPROTECT] => 1
            [PROFILE] =>
            [USE_DB] =>
        )

>> Einstellungen für Plugin "search" (Stichwortsuche)

    [SEARCH] => Array
        (
            [TARGET] => _self
        )

>> Einstellungen für Plugin "user_admin" (Nutzerverwaltung)

    [USER] => Array
        (
            [ALLOW_CREATE] => 0
        )

)

<?php
/* die gewählte Hintergrundfarbe auslesen */
$string = $YANA->getVar("PROFILE.BGCOLOR");
print '<p style="background-color: '.$string.'">test</p>';
?>
Default-Einstellungen
<?php
global $YANA;

/* YANA Defaut-Einstellungen ausgeben */
$array = $YANA->getVar("DEFAULT");
print_r($a);
?>
Ausgabe:
    Array
        (

>> Legt fest, welche Aktion automatisch aufgerufen werden soll, wenn das
   Argument "action" leer oder nicht gesetzt ist.
   Voreingestellt ist "sitemap" - man kann aber z.Bsp. auch "guestbook_read"
   verwenden für das Gästebuch, oder "search_start" für die Suchmaschine.
   Diese Einstellung wurde eingeführt in Version 2.8.0

            [HOMEPAGE] => sitemap

>> Legt fest, ob Textmeldungen (Fehler, Hinweise etc.) in einem eigenen Fenster (true)
   oder im Text der normalen Seite (false) angezeigt werden sollen.
   Diese Einstellung wurde eingeführt in Version 2.8.2

            [MESSAGE] => false

>> Default-Event Konfiguration für Ereignisse, die nicht definiert sind

            [EVENT] => Array
                (
                    [TYPE] => default
                    [MODE] => 0
                    [PERMISSION] => 0
                    [TEMPLATE] => index
                    [INSERT] =>
                )

>> Default-Interface Konfiguration

            [INTERFACE] => Array
                (
                    [TEST] => Array
                        (
                            [TYPE] => private
                            [MODE] => 0
                            [PERMISSION] => 0
                            [TEMPLATE] => NULL
                        )

                )

>> Default-Skin Konfiguration

            [SKIN] => Array
                (
                    [DIRECTORY] => default/
                )

>> Default-Language Konfiguration

            [LANGUAGE] => Array
                (
                    [DIRECTORY] => de/
                )

>> Voreingestellung für Datenbankverbindungen

            [DATABASE] => Array
                (
                    [DSN] => Array
                        (
                            [USE_ODBC] =>
                            [DBMS] => mysql
                            [HOST] => localhost
                            [PORT] => 0
                            [USERNAME] => root
                            [PASSWORD] =>
                            [DATABASE] => yana
                        )

>> Konfiguration der Datenbankschnittstelle

                    [OPTIONS] => Array
                        (
                            [AUTOFREE] => 1
                            [PERSISTENT] => 1
                            [SSL] =>
                        )

>> Liste der DBMS, welche über die ODBC-Schnittstelle angesprochen werden sollen

                    [REQUIRE_ODBC] => Array
                        (
                            [0] => db2
                            [1] => access
                        )

                )

        )
Nutzer-Informationen
<?php
global $YANA;

/* Nutzer IP */
print $YANA->getVar("REMOTE_ADDR")."\n";
/* Nutzer Name */
print $YANA->getVar("SESSION_USER_ID")."\n";
/* Zugriffslevel des Nutzers */
print $YANA->getVar("PERMISSION")."\n";
/* Session-Name */
print $YANA->getVar("SESSION_NAME")."\n";
/* Session-ID */
print $YANA->getVar("SESSION_ID")."\n";
?>

Ausgabe:
127.0.0.1
ADMINISTRATOR
100
YSID
480f97e69eae2311d3157cc3377a2d73

Verwendung eines CAPTCHA

Allgemeines zum Verständnis

Ein CAPTCHA ist eine Methode zum Schutz vor Spam. Dazu wird eine Grafik mit einem Text angezeigt, welchen der Besucher abtippen muss. Ein Mensch kann das mit Leichtigkeit, ein Spam-Bot hingegen kann das nicht. Auf diese Weise kann eine große Menge unerwünschter Werbung vermieden werden.

Das Framework hat eine Funktion zum Erzeugen einer CAPTCHA-Grafik im PNG-Format (Mime-Type "image/png"), welche einen zufällig erzeugten Code aus Zahlen und Buchstaben enthält. Ein Parameter gibt an, welche Positionsnummer dieser Code in der aktuellen Code-Tabelle hat. Die Codetabelle enthält 10 Einträge und verfällt in einem Zeitraum von 10 Minuten bis etwa 3 Stunden nach dem Aufruf der Funktion automatisch. Wenn die Tabelle abgelaufen ist, wird automatisch eine neue Tabelle erstellt.

Wie benutze ich ein CAPTCHA für mein Plugin?

Das Yana Framework hat eine solche Funktion bereits eingebaut. Sie müssen sich also nicht selbst darum kümmern, sondern es lediglich benutzen.

Das CAPTCHA besteht aus zwei Teilen: einer Grafik mit einem Input-Feld, welche im Template eingebunden werden müssen und einer Abfrage, welche im Quellcode des Plugins eingebunden werden muss und die true beziehungsweise false liefert, wenn die Eingabe korrekt beziehungsweise falsch war.

Dazu folgendes Beispiel:

Quellcode des Templates:
[%captcha%]

Screenshot
Abbildung: Beispiel für die Darstellung im Browser

Quellcode des Plugins:
<?php
global $YANA;

/**
 * zum Prüfen der Eingabe:
 *
 * Die Variable $formular_daten kann je nach Bedarf auf
 * $_POST, $_GET, oder $ARGS gesetzt werden.
 */
$bool = $YANA->handle("security_check_image", $formular_daten);
if ($bool) { print "Eingabe korrekt."; } else { print "Eingabe ist falsch."; } ?>

Einbau in älteren Versionen vor 2.9.3

Die Unterstützung für CAPTCHAs wurde in Version 2.8.0 eingeführt. Das obige Beispiel gilt für das Yana Framework ab Version 2.9.3. In dieser Version wurde die Handhabung des CAPTCHA deutlich vereinfacht.

Für die älteren Versionen 2.8.0 bis 2.9.2 verwenden Sie bitte das folgende Beispiel:

Quellcode des Template:
<input type="hidden" name="security_image_index" value="[%$SECURITY_IMAGE_INDEX%]">
<img src=[%"action=security_get_image&security_image_index=$SECURITY_IMAGE_INDEX"|url%]>
<input type="text" name="security_image">
Quellcode des Plugins:
<?php
global $YANA;

/* zum Erzeugen des Formulars: */
/* Die Variable SECURITY_IMAGE_INDEX muss für das Formular gesetzt werden.
   Sie kann einen beliebigen Integerwert zwischen 1 und 9 haben. */
$YANA->setVar("SECURITY_IMAGE_INDEX", rand(1,9));

/**
 * zum Prüfen der Eingabe:
 *
 * Die Variable $formular_daten kann je nach Bedarf auf
 * $_POST, $_GET, oder $ARGS gesetzt werden.
 */
$bool = $YANA->handle("security_check_image", $formular_daten);
if ($bool) { print "Eingabe korrekt."; } else { print "Eingabe ist falsch."; } ?>

Für noch ältere Versionen (älter als Version 2.8.0) ist ein Einbau von Hand erforderlich.

Plugins editieren

Wie definiere ich die Schnittstellen?

Die Schnittstelle eines Plugins wird als Datei mit der Endung "*.config" gespeichert. Sie finden diese Dateien im Verzeichnis "plugins/".

/* in der Schnittstellenbeschreibung plugins/foo.config */

<INTERFACE>
	<name der aktion>

		<TYPE>primary|default|write|read|security|config</TYPE>
/* Type:
 - "primary"  für Kernprozesse eines Hauptprogramms
 - "security" für sicherheitsrelevante Funktionen, wie das Prüfen von Passwörtern
 - "config"   für Funktionen zum Editieren von Konfigurationsdateien
 - "write"    für Schreibzugriffe auf dem Dateisystem oder einer Datenbank
 - "read"     für Lesezugriffe auf dem Dateisystem oder einer Datenbank
 - "default"  ist gedacht für Entwickler, die sich unschlüssig sind, wo die Aktion einzuordnen ist
*/
		<MODE>0|1</MODE>
/* Mode:
 - 0 (default) normaler Betriebsmodus
 - 1           Aktion im Default-Konfiguration ("abgesicherter Modus") starten
               (für sicherheitskritische Aufgaben)
*/
		<TEMPLATE>Id des Templates (z.Bsp. INDEX)</TEMPLATE>
		<INSERT>Id des Templates (z.Bsp. MY_TEMPLATE)</INSERT>
/* Templates:
 Namen von Templates für die Ausgabe
 - das unter "INSERT" angegebene Datei wird in die "TEMPLATE"-Datei eingebettet
 - "TEMPLATE" bildet also einen statischen "Rahmen" um den Inhalt, Defaultwert ist "INDEX"
 - Der Name des Templates entspricht dem Namen, der in der Skindatei festgelegt wurde.
   Zum Vergleich öffnen Sie bspw. die Datei skins/default/default.config .
 - Das spezielle Template "NULL" unterbindet dass eine Ausgabe erzeugt wird
   (sehr praktisch wenn die Ausgabe keine HTML-Datei sondern bspw. eine PNG-Grafik werden soll)
 - Das spezielle Template "MESSAGE" erzeugt eine Textmeldung.
*/

		<PERMISSION>1</PERMISSION>
/* Permission:
 Gibt an, welche Zugriffsrechte für einen Nutzer mindestens erforderlich sind,
 um die Aktion aufrufen zu können. Der Wert liegt zwischen 0 und 100, wobei
 der Wert 0 = "keine Beschränkung" bedeutet. Sie können eine Funktion temporär
 deaktivieren, indem Sie die Permission auf -1 setzen. In diesem Fall kann niemand
 die Aktion aufrufen.
*/
		<ONSUCCESS>
			<TEXT>Name der Textmeldung</TEXT>
			<GOTO>Name der Aktion</GOTO>
		</ONSUCCESS>
		<ONERROR>
			<TEXT>Name der Textmeldung</TEXT>
			<GOTO>Name der Aktion</GOTO>
		</ONERROR>
/* OnSuccess / OnError:
 Sie können eine Aktion angeben, auf welche automatisch weitergeleitet werden soll,
 wenn die Aktion erfolgreich war beziehungsweise, wenn ein Fehler aufgetreten ist.

 Zusätzlich können Sie eine Textmeldung angeben, welche angezeigt werden soll.
 Eine Liste der Textmeldungen finden Sie in der Datei "languages/de/message.config".
*/
	</name der aktion>

/* ein Beispiel */
        <foo>
		<TYPE>write</TYPE>
		<MODE>0</MODE>
		<TEMPLATE>MESSAGE</TEMPLATE>
		<PERMISSION>75</PERMISSION>
		<ONSUCCESS>
			<GOTO>foo_read</GOTO>
		</ONSUCCESS>
		<ONERROR>
			<GOTO>foo_edit</GOTO>
		</ONERROR>
        <foo>
</INTERFACE>

in der Plugin-Klasse plugins/foo/plugin.php:
<?php
class plugin_foo extends plugin
{

    /* ... */

    function foo($ARGS)
    {
        /* Quelltext der Aktion "foo" */
        if ($test) {
            return true; /* true = SUCCESS -> gehe zu Aktion "foo_read" */
        } else {
            return false; /* false = ERROR -> gehe zu Aktion "foo_edit" */
        }
    }

    function foo_edit($ARGS)
    {
        /* Quelltext der Aktion "foo_edit" */
    }

    function foo_read($ARGS)
    {
        /* Quelltext der Aktion "foo_read" */
    }

}
?>

Wie erstelle ich neue Aktionen?

Zuerst sollten Sie mit Hilfe des SDK ein Grundgerüst für Ihr neues Plugin generieren lassen. Dies macht das Anpassen des Quellcodes deutlich einfacher.

Für das Erstellen einer neuen Aktion sind zwei Dinge erforderlich. Einerseits das Schreiben des Quellcodes und andererseits die Registrierung dieser neuen Aktion im Framework selbst durch Publizieren der Schnittstelle. Dadurch wird es überhaupt erst möglich, die Aktion aufzufinden und zu benutzen.

Im Folgenden ein Beispiel: Alle öffentlichen Funktionen der Klasse stellen eine Funktion bereit, die ebenso heißt, wie die Funktion selbst. Also: um eine Aktion "foo" zu erzeugen, erstellen Sie eine Funktion "foo()". Diese rufen Sie in der URL auf über: "index.php?action=foo".

Achten Sie im Folgenden Beispiel auf die "Hot-Spots". Diese markieren Stellen im Skelett der Anwendung, welche mit eigenem Code befüllt werden können.

<?php
class plugin_beispiel extends plugin
{

    function plugin_beispiel($plugin_name)
    {
        settype($plugin_name,"string");
        global $YANA;

        $this->plugin_name = $plugin_name;
    }

    /**
     * Default event handler
     *
     * @param  string $event name of the called event in lower-case
     * @param  array  $ARGS  array of params passed to the function
     * @return boolean
     */
    function _default($event, $ARGS)
    {
        settype($event, "string");
        settype($ARGS, "array");

        # HOT-SPOT << hier können Sie Aktionen definieren

        # zum Beispiel mit einer Switch-Anweisung:

        switch ($event)
        {
            case 'my_action1':
                # HOT-SPOT << Code für Aktion 'my_action1'
            break;
            case 'my_action2':
                # HOT-SPOT << Code für Aktion 'my_action2'
            break;
        }

        return true;
    }

    /**
     * Type: read
     * Permission: 0
     * Templates: index entries
     *
     * @param array $ARGS array of params passed to the function
     * @return boolean
     */
    function guestbook_read_entries ($ARGS)
    {
        # HOT-SPOT << Code für Aktion 'guestbook_read_entries'
    }

/* { ... } */

    /**
     * Type: write
     * Permission: 100
     * Templates: MESSAGE
     *
     * @param array $ARGS array of params passed to the function
     * @return boolean
     */
    function guestbook_write_write ($ARGS)
    {
        # HOT-SPOT << Code für Aktion 'guestbook_write_write'
        $YANA->message("OK", "200");
    }

    function my_action ($ARGS)
    {
        # HOT-SPOT << Code für Aktion 'my_action'
    }
}
?>

Die "Hot-Spots", an welchen der Entwickler eigenen Quellcode schreiben oder ergänzen kann, sind in diesem kurzen Beispiel entsprechend hervorgehoben. Die Funktion "my_action" soll demonstrieren, wie man nachträglich eigene Aktionen zur Schnittstelle der Klasse und damit zum Plugin hinzufügen kann. Beachten Sie die Funktion "_default". Diese wird von der Basisklasse "plugin" geerbt und fungiert als "Default event handler", welcher alle Ereignisse abfängt, die an das Plugin gesendet werden, aber über die Schnittstelle der Klasse nicht implementiert sind. Außerdem fängt diese Funktion Exoten ab, wie beispielsweise Ereignisse welche ungünstigerweise ebenso benannt sind wie der Konstruktor der Klasse selbst, oder solche, welche von der Basisklasse "plugin" geerbt wurden und somit nicht zur vom Nutzer definierten Schnittstelle der Klasse gehören können. Dies betrifft aus Sicherheitsgründen auch solche, welche in der abgeleiteten Klasse reimplementiert werden. Der Grund hierfür ist, dass diese Methoden öffentlich sind. Sie sind somit Teil einer gemeinsamen Schnittstelle aller von der Klasse "plugin" abgeleiteten Klassen. Ihre Funktionalität wird folglich gewissermaßen durch die Implementierung der Basisklasse vorgegeben und zugesichert. Sie sollte auch in den abgeleiteten Klassen erhalten bleiben.

Um eine Funktion zu erzeugen, die nicht in der öffentlichen Schnittstelle auftauchen soll, kennzeichnen sie diese Funktion als "private".

Liste neu Laden

Bitte beachten: damit die neuen Funktionen verfügbar werden, müssen Sie den Plugin-Cache erneuern. Dazu loggen Sie sich als Administrator ein und klicken im Administrationsmenü auf "Liste neu laden".

Wie erstelle ich ein Setup-Menü?

Die "Setup-Menüs" finden Sie im Administrationsmenü in der Spalte "Optionen" (links), wie in folgender Abbildung.

Liste neu Laden

Um den Menüeintrag und das dazu passende Setup zu erzeugen, genügt ein Eintrag in der Konfigurationsdatei des Plugins und ein HTML-Template. Es ist dazu nicht erforderlich PHP-Code zu schreiben. Betrachte Sie folgendes Beispiel der Konfigurationsdatei eines Plugins:

Datei "plugins/beispiel.config"

<INFO>
	/* Zuerst die obligatorischen Angaben - diese haben mit dem
	 * Setup-Menü noch nichts zu tun.
	 */
	<ID>foo</ID>
	<NAME>Foo plugin</NAME>
	<AUTHOR>Thomas Meyer</AUTHOR>
	<DESCRIPTION>mein Beispiel-Plugin</DESCRIPTION>
	<LOGO>%PLUGINDIR%foo/preview.jpg</LOGO>
	<IMAGE>%PLUGINDIR%foo/icon.png</IMAGE>
	<TYPE>primary</TYPE>
	/* Hier folgen die Einträge für das Setup-Menü */
	<SETUP>
		/* Der folgende Code erzeugt einen Eintrag mit
		 * der Beschriftung "Foo Options" und dem Icon
		 * "plugins/foo/setup1.gif". Bei Klick auf die
		 * Schaltfläche "Setup" wird die Aktion
		 * "foo_setup_1" ausgelöst.
		 */
		<0>
			<ACTION>foo_setup_1</ACTION>
			<TITLE>Foo Options</TITLE>
		</0>
		/* Ein zweites Beispiel: */
		<1>
			<ACTION>foo_setup_2</ACTION>
			<TITLE>Bar Options</TITLE>
		</1>
	</SETUP>
</INFO>

<INTERFACE>

	/* Den Aktionen "foo_setup_1" und "foo_setup_2"
	 * wird nun noch ein Template zugeordnet
	 */
	<foo_setup_1>
		/* TYPE=config definiert, dass es ein Setup-Menü ist */
		<TYPE>config</TYPE>
		/* PERMISSION=100 beschränkt den Zugriff auf Nutzer
		 * mit der Sicherheitsstufe 100 - das sind Administratoren.
		 */
		<PERMISSION>100</PERMISSION>
		/* foo_template_1 ist der Name des Templates */
		<INSERT>foo_template_1</INSERT>
	</foo_setup_1>

	<foo_setup_2>
		<TYPE>config</TYPE>
		<PERMISSION>75</PERMISSION>
		<INSERT>foo_template_2</INSERT>
	</foo_setup_2>

	/* ... hier folgen noch eventuell andere Aktionen ... */

</INTERFACE>

Nun benötigen Sie noch eine HTML-Seite mit einem Formular, wie in folgendem Beispiel:

Datei "skins/default/beispiel.html"
<!-- Den Kopf der Datei sollten Sie einfach übernehmen. Hier gibt es nichts
     zu editieren. Copy'n'Paste reicht völlig aus. -->

<!-- BEGINN: Kopf -->
<form method="POST" enctype="multipart/form-data" action="[%$PHP_SELF%]">
[%if !$ID%][%if $PERMISSION==100%]
	<input type="hidden" name="action" value="set_config_profile">
[%/if%][%else%]
	<input type="hidden" name="action" value="set_config_profile">
[%/if%]
	<input type="hidden" name="[%$SESSION_NAME%]" value="[%$SESSION_ID%]">
	<input type="hidden" name="id" value="[%$ID%]">
<!-- ENDE: Kopf -->

<!-- Nun folgt der variable Teil, den Sie selbst ausfüllen können -->

	<!-- eine Überschrift macht sich gut: -->
	<h1>Setup</h1>

	<!-- eine Liste mit Optionen -->
	<label>Option 1
	<!-- $PROFILE.OPT1 ist der gespeicherte Wert für dieses Feld -
	     sofern bereits einmal ein Wert gespeichert wurde.
	     Der Modifier |entities sorgt dafür, Tag-Klammern und
	     Anführungszeichen in HTML-Entitäten umgewandelt werden, damit
	     keine HTML-Syntaxfehler entstehen können.
	 -->
	<input type="text" name="opt1" value="[%$PROFILE.OPT1|entities]">
	</label><br>

	<label>Option 2
	<input type="text" name="path.opt2" value="[%$PROFILE.PATH.OPT2|entities]">
	</label><br>

	<label>Option 3
	<input type="text" name="opt3" value="[%$PROFILE.OPT3|entities]">
	</label><br>

	<!-- die Schaltfläche zu Abschicken nicht vergessen -->
	<input type="submit" value="[%$LANGUAGE.SPEICHERN%]">

</form>

Diese HTML-Seite bewirkt, dass nach dem Abschicken des Formulars folgendes Array gespeichert wird:

<?php
$PROFILE = array(
    'opt1' => "foo",
    'path' => array(
        'opt2' => "bar"
    ),
    'opt3' => "foobar"
);
?>

Sie können in Ihrem Plugin wie folgt auf die gespeicherten Optionen zugreifen:

<?php
global $YANA;
$opt1 = $YANA->getVar('PROFILE.OPT1');
$path_opt2 = $YANA->getVar('PROFILE.PATH.OPT2');
$opt3 = $YANA->getVar('PROFILE.OPT3');
?>

Damit das Formular "beispiel.html" bei Klick auf die Schaltfläche "Setup" auch angezeigt wird, muss es mit der Aktion "foo_setup_1" verknüpft werden. Dies geht wie folgt:

Datei "skins/default/beispiel.config"
<!-- Hier wird zunächst das Template unter dem Namen "foo_template_1" definiert ... -->
<foo_template_1>
	<FILE>beispiel.html</FILE>
</foo_template_1>

Datei "plugins/beispiel.config"

...

<INTERFACE>

	<foo_setup_1>
		<TYPE>config</TYPE>
		<PERMISSION>100</PERMISSION>
	<!-- ... und hier wird das Template "foo_template_1" der Aktion "foo_setup_1" zugeordnet. -->
		<INSERT>foo_template_1</INSERT>
	</foo_setup_1>
...

</INTERFACE>

Grafiken und Fotos

Wie lade ich eine Grafik aus einer Datei?

<?php
$image = new Image('dateiname');
// zum Beispiel:
$image = new Image('ordner/datei.png');
?>

Wie lade ich eine Grafik aus einem String?

<?php
$content = file_get_contents('ordner/datei.png');
$image = new Image($content, 'png');
?>

Wie erzeuge ich eine neue (leere) Grafik?

<?php
$image = new Image();
$width = 640;
$height = 480;
$image->resize($width, $height);
?>

Wie erzeuge ich ein Thumbnail?

<?php
$image = new Image('ordner/datei.png');
$width = 50;
// wenn die Höhe ($height) nicht angegeben wird,
// dann wird die Grafik proportional verkleinert
$image->resize($width);
$image->outputToFile('ordner/thumbnail.png');
?>

 Wie erstelle ich ein Upload-Formular für Bilder?

HTML-Code:
<form method="POST" action="%PHP_SELF%" enctype="multipart/form-data">
 (...)
Upload image: <input type="file" name="my_image" />
 (...)
</form>
PHP-Code:
<?php
// get data from form field 'my_image'
$id = 'my_image';
// output to directory 'foo/bar/' using filename 'image'
// (extension will be determined automatically)
$file = 'foo/bar/image';
// output as png image
$type = 'png';
// limit upload to 150 kbyte
$size = 150000;
// resize to 150px x 200px
$width = 150;
$height = 200;
// leave aspect-ratio untouched
$ratio = true;
// set background color to gray
$color = array(80, 80, 80);

// call method
$result = Image::uploadFile($id, $file, $type, $size, $width, $height, $ratio, $color);

// check for errors
if (is_string($result)) {

    print "The image was successfully uploaded to '$result'";

// error handling
} else {

    switch ($result)
    {
        case UPLOAD_ERR_SIZE:
        case UPLOAD_ERR_INI_SIZE:
        case UPLOAD_ERR_FORM_SIZE:
            die('File too big!');
        break;

        case UPLOAD_ERR_NO_FILE:
            die('No file has been uploaded!');
        break;

        case UPLOAD_ERR_INVALID_TARGET:
            die("Unable to write to file: '$file'");
        break;

        case UPLOAD_ERR_FILE_TYPE:
            die('The file is not a recognized image!');
        break;

        default:
            die('Some unexpected error occured!');
        break;
    }

}
?>

Wie zeichne ich Linien, geometrische Flächen und Text?

<?php
// erzeuge leeres Bild
$image = new Image();
$width = 180;
$height = 120;
$image->resize($width, $height);

// setze die Linienbreite auf 3px (optional)
$image->setLineWidth(3);

// die Leinwand mit einer Hintergrundfarbe füllen
$x = 0;
$y = 0;
$image->fill($image->white, $x, $y);

// Zeichne eine Linie
$x1 = 10;
$y1 = 10;
$x2 = 100;
$y2 = 30;
$image->drawLine($x1, $y1, $x2, $y2, $image->black);

// Zeichne einen Kreis
$x = 30;
$y = 50;
$width = 50;
$image->drawEllipse($x, $y, $width);

// Zeichne ein Rechteck
$x = 10;
$y = 60;
$width = 100;
$height = 50;
$rahmenFarbe = $image->black;
$fuellFarbe = $image->navy;
$image->drawRectangle($y, $y, $width, $height, $rahmenFarbe, $fuellFarbe);

// Zeichne ein Dreieck (oder anderes Polygon)
$points = array(
0 => array( 20, 0 ),
1 => array( 40, 20 ),
2 => array( 0, 20 )
);
$x = 50;
$y = 80;
$rahmenFarbe = $image->black;
$fuellFarbe = $image->yellow;
$image->drawPolygon($points, $x, $y, $rahmenFarbe , $fuellFarbe);

// Schreibe einen Text
$text = 'Hallo Welt!';
$x = 70;
$y = 40;
$textFarbe= $image->black;
$image->drawString($text, $x, $y, $textFarbe);

// Verwenden von Pinseln

// neuen Pinsel erzeugen
$brush = new Brush('small star');
// setze Größe des Pinsels auf 10px
$brush->setSize(10);
// setze die Farbe des Pinsels auf rot
$brush->setColor(255, 0, 0);
// den Pinsel auswählen
$image->setBrush($brush);

// zeichne einen Punkt und benutze dabei den Pinsel
$x = 150;
$y = 100;
$image->drawPoint($x, $y, IMG_COLOR_BRUSHED);

// Ausgabe der Grafik an den Browser
$image->outputToScreen('png');
exit;
?>

Abbildung
Abbildung: Ausgabe des Skripts

Details zur Verwendung von Farben

Wenn Sie mit Grafiken arbeiten, dann brauchen Sie Farben, um Linien, Texte oder Flächen zu zeichnen.

Es gibt 17 vordefinierte Farben. Diese lauten:

  1. $image->aqua
  2. $image->black
  3. $image->blue
  4. $image->fuchsia
  5. $image->gray
  6. $image->green
  7. $image->grey (Alias von $image->gray)
  8. $image->lime
  9. $image->maroon
  10. $image->navy
  11. $image->olive
  12. $image->purple
  13. $image->red
  14. $image->silver
  15. $image->teal
  16. $image->white
  17. $image->yellow

Weitere Farben können Sie erhalten durch Aufruf von: $color = $image->getColor($rot, $gruen, $blau); Dabei dürfen $rot, $gruen und $blau ganze Zahlen zwischen 0 und 255 sein.

Es ist wichtig, dass Sie verstehen, dass eine Farbe kein Objekt ist, dass für sich selbst existiert, sondern eine spezifische Eigenschaft einer Grafik. Das kommt daher, dass jede Grafik eine eigene Farbpalette besitzt und jede Farbe ein Teil (mathematisch gesprochen ein "Element") dieser Palette ist.

Die Palette des Bildes ist eine indexierte Menge aller in der Grafik enthaltenen Farben. Eine Farbe wird dabei dargestellt als ganze Zahl. Genauer: es handelt sich um Indexnummer der Farbe innerhalb der Farbpalette des Bildes. Das heißt, die Zahl 1 bezeichnet beispielsweise die Farbe, welche in der Farbpalette der Grafik die Positionsnummer 1 hat. Diese Farbe könnte am Bildschirm zum Beispiel "rot" aussehen. Beachten Sie jedoch, dass diese Zuordnung abhängig ist von der Farbpalette und somit vom gerade angezeigten Bild.

Welche Grafikfilter und -effekte kann ich verwenden?

Hier eine Liste interessanter Methoden der Klasse Image und was diese bewirken:

<?php
$image = new Image('foo.png');

/* Helligkeit einstellen
 *
 * Zahl zwischen -1.0 und +1.0 (-100% und +100%)
 */
$ammount = 0.5; /* 0.5 = +50% */
$image->brightness($ammount);
?>

Abbildung
Abbildung: Ausgabe des Skripts

<?php
/* Kontrast einstellen
 *
 * Zahl zwischen -1.0 und +1.0 (-100% und +100%)
 */
$ammount = 0.5; /* 0.5 = +50% */
$image->contrast($ammount);
?>

Abbildung
Abbildung: Ausgabe des Skripts

<?php
/* Unscharfmaske anwenden
 *
 * Zahl zwischen 0.0 und +1.0 (0% und +100%)
 */
$ammount = 0.8; /* 0.8 = 80% */
$image->blur($ammount);
?>

Abbildung
Abbildung: Ausgabe des Skripts

<?php
/* Bildschärfe erhöhen
 *
 * Zahl zwischen 0.0 und +1.0 (0% und +100%)
 */
$ammount = 0.8; /* 0.8 = 80% */
$image->sharpen($ammount);
?>

Abbildung
Abbildung: Ausgabe des Skripts

<?php
/* in Graustufen umwandeln
 */
$image->toGrayscale();
?>

Abbildung
Abbildung: Ausgabe des Skripts

<?php
/* Einfärben (Kolorieren)
 *
 * $rot, $gruen, $blau = Zahlen zwischen -255 und 255
 *
 * Der Farbwert wird zur Farbe der Grafik addiert
 */
$rot = -80;
$gruen = -40;
$blau = 120;
$image->colorize($rot, $gruen, $blau);
?>

Abbildung
Abbildung: Ausgabe des Skripts

<?php
/* Multiplizieren
 *
 * $rot, $gruen, $blau = Zahlen zwischen 0 und 255
 *
 * Der Farbwert wird mit der Farbe der Grafik multipliziert
 */
$rot = 100;
$gruen = 255;
$blau = 50;
/* dieses Beispiel reduziert den Rot- und Blaukanal */
$image->multiply($rot, $gruen, $blau);
?>

Abbildung
Abbildung: Ausgabe des Skripts

<?php
/* Monochromatischer Filter
 *
 * $rot, $gruen, $blau = Zahlen zwischen 0 und 255
 *
 * Färbt die Grafik mit der angegeben Farbe ein.
 */
$rot = 130;
$gruen = 180;
$blau = 200;
$image->monochromatic($rot, $gruen, $blau);
?>

Abbildung
Abbildung: Ausgabe des Skripts

<?php
/* Farbwerte umkehren (Negativeffekt)
 */
$image->negate();
?>

Abbildung
Abbildung: Ausgabe des Skripts

Details und Beispiele zu weiteren Funktionen finden Sie in der API-Dokumentation.

Erzeugen mehrspaltiger Layouts

Allgemeines zum Verständnis

Das Yana Framework verfügt über vordefiniertes CSS zum Erzeugen von Texten oder Seiten mit 2, 3 oder mehr vertikalen Spalten. Dazu ist keine Programmierung Ihrerseits erforderlich. Der erforderliche CSS-Code wird im "Default"-Skin automatisch geladen.

Im Folgenden folgen einige Beispiele zur Demonstration

Wie erzeuge ich 2 Spalten?

Quellcode des Templates:

<div class="multicol2">
    <div class="col_left">
        <h2>Spalte 1</h2>

        Nulla ultrices lacinia mi. Nulla dapibus, risus vitae imperdiet
        commodo, ipsum ligula lacinia orci, non venenatis metus ligula
        sit amet turpis. Nunc accumsan tempor nulla. Vivamus eleifend,
        lectus eu feugiat consequat, mi lacus vestibulum velit, eu
        egestas purus nunc ac est. Mauris massa lorem, lacinia non,
        condimentum vel, cursus ac, lectus. Nulla tempor molestie quam.
        Aenean dapibus nisl nonummy quam. Mauris pellentesque ornare
        ante. Integer a urna ultricies neque bibendum dignissim.
        Suspendisse interdum nisl. In rhoncus. Vivamus risus mi, semper
        id, lobortis et, auctor in, nulla. Sed placerat posuere tortor.
        In vitae augue.

    </div>
    <div class="col_right">
        <h2>Spalte 2</h2>

        Aliquam auctor viverra ligula. Ut nisi felis, condimentum at,
        aliquam eget, tempus id, nisi. Maecenas a libero. Nulla metus
        mi, malesuada sit amet, sagittis bibendum, scelerisque a, purus.
        Nunc ipsum. Sed vel augue pellentesque ligula pharetra pulvinar.
        Class aptent taciti sociosqu ad litora torquent per conubia
        nostra, per inceptos hymenaeos. Nam orci. Donec neque pede,
        iaculis in, pellentesque ac, commodo eget, libero. Sed vel
        magna.

    </div>
    <div class="col_foot">&nbsp;</div>
</div>
Spalte 1
Nulla ultrices lacinia mi. Nulla dapibus, risus vitae imperdiet commodo, ipsum ligula lacinia orci, non venenatis metus ligula sit amet turpis. Nunc accumsan tempor nulla. Vivamus eleifend, lectus eu feugiat consequat, mi lacus vestibulum velit, eu egestas purus nunc ac est. Mauris massa lorem, lacinia non, condimentum vel, cursus ac, lectus. Nulla tempor molestie quam. Aenean dapibus nisl nonummy quam. Mauris pellentesque ornare ante. Integer a urna ultricies neque bibendum dignissim. Suspendisse interdum nisl. In rhoncus. Vivamus risus mi, semper id, lobortis et, auctor in, nulla. Sed placerat posuere tortor. In vitae augue.
Spalte 2
Aliquam auctor viverra ligula. Ut nisi felis, condimentum at, aliquam eget, tempus id, nisi. Maecenas a libero. Nulla metus mi, malesuada sit amet, sagittis bibendum, scelerisque a, purus. Nunc ipsum. Sed vel augue pellentesque ligula pharetra pulvinar. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Nam orci. Donec neque pede, iaculis in, pellentesque ac, commodo eget, libero. Sed vel magna.
 

Wie erzeuge ich 3 Spalten?

Quellcode des Templates:

<div class="multicol3">
    <div class="col_left">
        <h2>Spalte 1</h2>

        Nulla ultrices lacinia mi. Nulla dapibus, risus vitae imperdiet
        commodo, ipsum ligula lacinia orci, non venenatis metus ligula
        sit amet turpis. Nunc accumsan tempor nulla. Vivamus eleifend,
        lectus eu feugiat consequat, mi lacus vestibulum velit, eu
        egestas purus nunc ac est. Mauris massa lorem, lacinia non,
        condimentum vel, cursus ac, lectus. Nulla tempor molestie quam.
        Aenean dapibus nisl nonummy quam. Mauris pellentesque ornare
        ante. Integer a urna ultricies neque bibendum dignissim.
        Suspendisse interdum nisl. In rhoncus. Vivamus risus mi, semper
        id, lobortis et, auctor in, nulla. Sed placerat posuere tortor.
        In vitae augue.

    </div>
    <div class="col_center">
        <h2>Spalte 2</h2>

        Aliquam auctor viverra ligula. Ut nisi felis, condimentum at,
        aliquam eget, tempus id, nisi. Maecenas a libero. Nulla metus
        mi, malesuada sit amet, sagittis bibendum, scelerisque a, purus.
        Nunc ipsum. Sed vel augue pellentesque ligula pharetra pulvinar.
        Class aptent taciti sociosqu ad litora torquent per conubia
        nostra, per inceptos hymenaeos. Nam orci. Donec neque pede,
        iaculis in, pellentesque ac, commodo eget, libero. Sed vel
        magna.

    </div>
    <div class="col_right">
        <h2>Spalte 3</h2>

        Morbi eget dolor. Etiam ut velit sollicitudin massa laoreet
        lobortis. Ut vel sem id enim ornare ultrices. Morbi justo
        tortor, blandit sed, euismod at, eleifend nec, tortor. Lorem
        ipsum dolor sit amet, consectetuer adipiscing elit. Etiam eget
        enim. Maecenas vel nisl dapibus metus venenatis volutpat.
        Integer ipsum ante, porta eu, porta vel, euismod in, magna.
        Fusce dolor quam, lacinia eget, rutrum at, lacinia pulvinar,
        risus. Nulla imperdiet, lorem facilisis lacinia suscipit, diam
        mi aliquet dui, at fringilla lectus mauris sit amet ipsum.
        Morbi eget sem quis est congue pulvinar. Vivamus fermentum
        dolor nec nisi convallis posuere. Aliquam eu diam. Ut suscipit,
        nisi quis vehicula ullamcorper, lectus lorem fermentum tellus,
        ut egestas arcu sapien aliquam massa.

    </div>
    <div class="col_foot">&nbsp;</div>
</div>
Spalte 1
Nulla ultrices lacinia mi. Nulla dapibus, risus vitae imperdiet commodo, ipsum ligula lacinia orci, non venenatis metus ligula sit amet turpis. Nunc accumsan tempor nulla. Vivamus eleifend, lectus eu feugiat consequat, mi lacus vestibulum velit, eu egestas purus nunc ac est. Mauris massa lorem, lacinia non, condimentum vel, cursus ac, lectus. Nulla tempor molestie quam. Aenean dapibus nisl nonummy quam. Mauris pellentesque ornare ante. Integer a urna ultricies neque bibendum dignissim. Suspendisse interdum nisl. In rhoncus. Vivamus risus mi, semper id, lobortis et, auctor in, nulla. Sed placerat posuere tortor. In vitae augue.
Spalte 2
Aliquam auctor viverra ligula. Ut nisi felis, condimentum at, aliquam eget, tempus id, nisi. Maecenas a libero. Nulla metus mi, malesuada sit amet, sagittis bibendum, scelerisque a, purus. Nunc ipsum. Sed vel augue pellentesque ligula pharetra pulvinar. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Nam orci. Donec neque pede, iaculis in, pellentesque ac, commodo eget, libero. Sed vel magna.
Spalte 3
Morbi eget dolor. Etiam ut velit sollicitudin massa laoreet lobortis. Ut vel sem id enim ornare ultrices. Morbi justo tortor, blandit sed, euismod at, eleifend nec, tortor. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Etiam eget enim. Maecenas vel nisl dapibus metus venenatis volutpat. Integer ipsum ante, porta eu, porta vel, euismod in, magna. Fusce dolor quam, lacinia eget, rutrum at, lacinia pulvinar, risus. Nulla imperdiet, lorem facilisis lacinia suscipit, diam mi aliquet dui, at fringilla lectus mauris sit amet ipsum. Morbi eget sem quis est congue pulvinar. Vivamus fermentum dolor nec nisi convallis posuere. Aliquam eu diam. Ut suscipit, nisi quis vehicula ullamcorper, lectus lorem fermentum tellus, ut egestas arcu sapien aliquam massa.
 

Wie erzeuge ich 4 und mehr Spalten?

Es ist möglich mehrspaltige Layouts ineinander zu schachteln. Das folgende Beispiel demonstriert, wie zwei 2-spaltige Layouts ineinander verschachtelt werden, um ein 4-spaltiges Layout zu erzeugen.

Quellcode des Templates:

<div class="multicol2">
    <div class="col_left">
        <div class="multicol2">
            <div class="col_left">
                <h2>Spalte 1</h2>

                Vestibulum tempor commodo mi. Integer sed nisi. Donec
                nulla elit, commodo porttitor, semper eget, sagittis
                viverra, urna. Duis pretium dui facilisis turpis.
                Mauris vel arcu. Donec ut lorem vel lorem aliquet
                commodo. Donec sollicitudin mattis lacus. Ut non magna
                sit amet tortor viverra sagittis. Ut venenatis.
                Vestibulum sodales sapien scelerisque erat. Integer
                accumsan orci et tortor vulputate mollis. Curabitur
                lacinia quam id libero. Nulla eu lorem eget mi mattis
                tempus. Suspendisse consectetuer. Vivamus at risus.
                Aenean malesuada.

            </div>
            <div class="col_right">
                <h2>Spalte 2</h2>

                Morbi id nisi. Proin fringilla eleifend mi. Nunc eget
                elit. Nam ligula nibh, euismod blandit, nonummy eu,
                porta non, magna. Ut id nisi id metus consectetuer
                euismod. Vestibulum ante ipsum primis in faucibus orci
                luctus et ultrices posuere cubilia Curae; Mauris
                blandit ultrices eros. Fusce in nisl sit amet enim
                consequat tristique. Sed facilisis eros convallis magna.
                Pellentesque justo. Praesent nec libero at velit
                malesuada nonummy. Mauris vitae lectus eget elit
                euismod bibendum. Nulla nec ligula. Curabitur metus.
                Integer lectus nulla, iaculis molestie, venenatis non,
                suscipit commodo, est. Sed pulvinar, justo eu pulvinar
                convallis, mi tellus pellentesque elit, eu aliquet
                sapien ligula non mauris.

            </div>
        </div>
    </div>
    <div class="col_right">
        <div class="multicol2">
            <div class="col_left">
                <h2>Spalte 3</h2>

                Praesent eu risus. Fusce feugiat. Maecenas eget lacus
                quis nisi blandit porttitor. Pellentesque sed turpis.
                Nulla facilisi. Aenean convallis dolor eget elit. Donec
                elementum, pede nec euismod varius, ante diam elementum
                lectus, vitae iaculis orci libero quis tortor.
                Vestibulum justo est, laoreet eu, consequat sed,
                molestie at, mi. Fusce luctus, odio eu imperdiet
                viverra, nunc arcu gravida ante, iaculis lacinia tortor
                arcu ac felis. Quisque sagittis aliquam nisi. Aliquam
                nonummy. Nulla mattis orci vel nunc. Nunc in odio.
                Proin mi risus, lobortis ac, mollis vitae, lacinia
                vehicula, nulla. Nunc nibh. Morbi laoreet pellentesque
                justo. Praesent ultrices.

            </div>
            <div class="col_right">
                <h2>Spalte 4</h2>

                Nullam eget lectus. Aenean non augue auctor erat luctus
                fermentum. Quisque aliquam eros vel ligula. Mauris pede
                velit, mollis eget, adipiscing non, placerat nec, erat.
                Vestibulum vel sem non orci porttitor congue. Cras
                pretium eros eget dui. Donec gravida. Sed mattis
                tincidunt enim. Donec aliquam, quam eu rhoncus gravida,
                nibh nunc egestas nulla, lobortis interdum nisi dui id
                nisi. Praesent tristique velit sit amet ante. Nam
                malesuada, nisi in laoreet venenatis, dolor pede
                vehicula nunc, tempus accumsan ante purus eget sapien.
                Praesent aliquam, lorem sit amet volutpat faucibus,
                ligula lorem auctor diam, vitae vulputate pede ligula
                et leo.

            </div>
        </div>
    </div>
    <div class="col_foot">&nbsp;</div>
</div>
Spalte 1
Vestibulum tempor commodo mi. Integer sed nisi. Donec nulla elit, commodo porttitor, semper eget, sagittis viverra, urna. Duis pretium dui facilisis turpis. Mauris vel arcu. Donec ut lorem vel lorem aliquet commodo. Donec sollicitudin mattis lacus. Ut non magna sit amet tortor viverra sagittis. Ut venenatis. Vestibulum sodales sapien scelerisque erat. Integer accumsan orci et tortor vulputate mollis. Curabitur lacinia quam id libero. Nulla eu lorem eget mi mattis tempus. Suspendisse consectetuer. Vivamus at risus. Aenean malesuada.
Spalte 2
Morbi id nisi. Proin fringilla eleifend mi. Nunc eget elit. Nam ligula nibh, euismod blandit, nonummy eu, porta non, magna. Ut id nisi id metus consectetuer euismod. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris blandit ultrices eros. Fusce in nisl sit amet enim consequat tristique. Sed facilisis eros convallis magna. Pellentesque justo. Praesent nec libero at velit malesuada nonummy. Mauris vitae lectus eget elit euismod bibendum. Nulla nec ligula. Curabitur metus. Integer lectus nulla, iaculis molestie, venenatis non, suscipit commodo, est. Sed pulvinar, justo eu pulvinar convallis, mi tellus pellentesque elit, eu aliquet sapien ligula non mauris.
Spalte 3
Praesent eu risus. Fusce feugiat. Maecenas eget lacus quis nisi blandit porttitor. Pellentesque sed turpis. Nulla facilisi. Aenean convallis dolor eget elit. Donec elementum, pede nec euismod varius, ante diam elementum lectus, vitae iaculis orci libero quis tortor. Vestibulum justo est, laoreet eu, consequat sed, molestie at, mi. Fusce luctus, odio eu imperdiet viverra, nunc arcu gravida ante, iaculis lacinia tortor arcu ac felis. Quisque sagittis aliquam nisi. Aliquam nonummy. Nulla mattis orci vel nunc. Nunc in odio. Proin mi risus, lobortis ac, mollis vitae, lacinia vehicula, nulla. Nunc nibh. Morbi laoreet pellentesque justo. Praesent ultrices.
Spalte 4
Nullam eget lectus. Aenean non augue auctor erat luctus fermentum. Quisque aliquam eros vel ligula. Mauris pede velit, mollis eget, adipiscing non, placerat nec, erat. Vestibulum vel sem non orci porttitor congue. Cras pretium eros eget dui. Donec gravida. Sed mattis tincidunt enim. Donec aliquam, quam eu rhoncus gravida, nibh nunc egestas nulla, lobortis interdum nisi dui id nisi. Praesent tristique velit sit amet ante. Nam malesuada, nisi in laoreet venenatis, dolor pede vehicula nunc, tempus accumsan ante purus eget sapien. Praesent aliquam, lorem sit amet volutpat faucibus, ligula lorem auctor diam, vitae vulputate pede ligula et leo.
 

Baummenüs erstellen

Allgemeines zum Verständnis

Das  Yana Framework bietet Ihnen zum Erstellen aufklappbarer Baummenüs mehrere Lösungen an. Aufwendige Programmierung ist dazu nicht erforderlich.

Folgende Möglichkeiten stehen Ihnen zur Verfügung:

  1. Sie können diese Menüs im HTML-Code selbst schreiben. Das Framework kümmert sich um die Darstellung. Sie behalten volle Kontrolle über den Code.
  2. Sie können den HTML-Code des Menüs automatisch generieren lassen und geben nur die Liste der Einträge an. In diesem Fall müssen Sie sich um den Code nicht mehr kümmern, sondern nur um die Inhalte.

Für beide Varianten haben Sie die Wahl zwischen derzeit zwei verschiedenen Layouts. Dieses Kapitel enthält folglich drei Abschnitte. Zuerst wird Ihnen jeweils für  1. und 2. Layout gezeigt, wie Sie den HTML-Quellcode der Menüs von Hand schreiben können.  Danach wird Ihnen demonstriert, wie Sie die Template-Funktion "printUnorderedList" verwenden können, um sich diese Menüs automatisch generieren zu lassen.

Wie erstelle ich ein aufklappbares Menü?

In diesem Abschnitt wird beschrieben, wie Sie ein aufklappbares Menü direkt im HTML erstellen können. Um die Funktionalität und die Darstellung kümmert sich das Yana Framework automatisch.

Dies ist der 1. Layoutvorschlag. Er verwendet JavaScript und CSS zur Darstellung des Menüs. Im Anschluss wird ein 2. Layoutvorschlag vorgestellt, welcher alternativ verwendet werden kann und ausschließlich CSS verwendet.

Das Layout wird in der Datei "skins/default/styles/menu.css" festgelegt und kann über folgende CSS-Klassen gesteuert werden:

Die Darstellung des Menüs entspricht den gängigen Empfehlungen und ist suchmaschinenfreundlich.

Gehen Sie wie folgt vor:


Abbildung: Darstellung des Menüs

<ul class="menu root">
   <li class="entry"><a href="ziel.html">Link</a></li>
   <li class="menu">
       <div onclick="yanaMenu(this)">Menü 1</div>
       <ul class="menu">
           <li class="entry"><a href="1.html">Eintrag 1</a></li>
       </ul>
   </li>
   <li class="menu">
       <div onclick="yanaMenu(this)">Menü 2</div>
       <ul class="menu">
           <li class="entry"><a href="2.html">Eintrag 2</a></li>
<li class="menu">
           <div onclick="yanaMenu(this)">Submenü 2.1</div>
               <ul class="menu">
                   <li class="entry">
<a href="2_1.html">Eintrag 2.1</a>
</li>
                   <li class="entry">
<a href="2_2.html">Eintrag 2.2</a>
</li>
                   <li class="entry">
<a href="2_3.html">Eintrag 2.3</a>
</li>
             </ul>
           </li>
       </ul>
   </li>
   <li class="menu">
       <div onclick="yanaMenu(this)">geschlossen</div>
       <ul class="menu" style="display: none;">
           <li class="entry"><a href="2.html">(unsichtbar)</a></li>
       </ul>
   </li>
</ul>

Das Attribut "onclick" enthält hier den Aufruf zum Öffnen und Schließen des Menüs. "Style"-Attribute legen abweichende Eigenschaften fest, wobei "display: none" das Menü ausblendet. Menüs sind von einem Element der CSS-Klasse "menu" umschlossen. Menüeinträge sind umschlossen von einem Element der CSS-Klasse "entry". Die Überschrift eines Menüs wird mit "div"-Tags umschlossen, welche auch das Attribut "onclick" erhalten. Durch Anklicken der Überschrift kann das Menü geschlossen oder geöffnet werden.

Tipp: es ist in der Regel einfacher, zunächst eine einfache Liste mit den Tags "ul", "li" zu erstellen und die CSS-Klassen und JavaScript-Codes nachträglich zu ergänzen, anstatt das Menü Zeile für Zeile zu beschreiben. Dadurch bleibt der Code während der Bearbeitung übersichtlicher.

Es gilt folgende Voreinstellung: alle Menüs sind zunächst geöffnet, wenn Sie nicht explizit als geschlossen gekennzeichnet sind. Es können mehrere Menüs gleichzeitig geöffnet sein.

Falls Sie wünschen, dass stets nur 1 Menü gleichzeitig geöffnet ist, fügen Sie folgenden Quellcode hinzu:

<script type="text/javascript">
    yana_menu_auto_close = true;
</script>

Falls Sie wünschen, dass zu Beginn alle Menüs geschlossen sind, verwenden Sie folgenden Quellcode:

<script type="text/javascript">
    yanaCloseAll();
</script>

Beide Varianten können kombiniert werden.

<script type="text/javascript">
    yana_menu_auto_close = true;
    yanaCloseAll();
</script>

Wie erstelle ich ein horizontales Menü?


Abbildung: Darstellung des Menüs

<ul class="hmenu">
  <li class="entry">
    <a href="ziel.html">Link 1</a>
  </li>
  <li onmouseover="yanaHMenu(this,true)" onmouseout=
  "yanaHMenu(this,false)" class="hmenu">
    <div class="menu_head">
      Menü 1
    </div>

    <ul class="hmenu">
      <li class="entry">
        <a href="1.html">Eintrag 1</a>
      </li>
    </ul>
  </li>
  <li onmouseover="yanaHMenu(this,true)" onmouseout=
  "yanaHMenu(this,false)" class="hmenu">
    <div class="menu_head">

      Menü 2
    </div>
    <ul class="hmenu">
      <li class="entry">
        <a href="2.html">Eintrag 2</a>
      </li>
      <li onmouseover="yanaHMenu(this,true)" onmouseout=
      "yanaHMenu(this,false)" class="hmenu">
        <div class="menu_head">
          Submenü 2.1
        </div>

        <ul class="hmenu">
          <li class="entry">
            <a href="2_1.html">Eintrag 2.1</a>
          </li>
          <li class="entry">
            <a href="2_2.html">Eintrag 2.2</a>
          </li>
          <li class="entry">

            <a href="2_3.html">Eintrag 2.3</a>
          </li>
        </ul>
      </li>
    </ul>
  </li>
  <li class="entry">
    <a href="3.html">Link 2</a>

  </li>
</ul>

Das Menü funktioniert vollständig mit CSS und ohne JavaScript. Allerdings wird hier zusätzlich JavaScript verwendet, damit ältere Browser und Browser mit unvollständiger CSS-Unterstützung, wie zum Beispiel der Internet Explorer 6.0, die Seite trotzdem wie erwartet darstellen.

Jedes Menü ist zunächst geschlossen und wird temporär geöffnet, wenn der Nutzer mit der Maus darauf zeigt.

Wenig Unterschiede zum vertikalen Menü gibt es bei den CSS-Klassen. Achten Sie lediglich darauf, dass hier statt der Klasse "menu" die Klasse "hmenu" verwendet wird.

Wie erstelle ich ein Baummenü?

Dies ist der 2. Layoutvorschlag. Die Menüs öffnen sich automatisch wenn Sie mit der Maus berührt werden. In Firefox, Opera und Co. funktioniert das Ein- und Ausklappen des Menüs vollständig über CSS (ohne JavaScript). Lediglich im Internet Explorer einschließlich Version 7 muss JavaScript aktiviert sein, da dieser Browser die erforderlichen CSS 2.1 Pseudoklassen noch nicht vollständig unterstützt.

Das Layout wird in der Datei "skins/default/styles/gui_array.css" festgelegt und kann über folgende CSS-Klassen gesteuert werden:

Gehen Sie wie folgt vor:


Abbildung: Darstellung des Menüs

<ul class="gui_array_list">
  <li class="gui_array_list">
    <a class="gui_array_value" href="ziel.html">Link 1</a>
  </li>
  <li class="gui_array_head"
      onmouseover="this.className='gui_array_head_open'"
      onmouseout="this.className='gui_array_head'">
    <span class="gui_array_key">Menü 1</span>
    <ul class="gui_array_list">
      <li class="gui_array_list">
        <a class="gui_array_value" href="1.html">Eintrag 1</a>
      </li>
    </ul>
  </li>
  <li class="gui_array_head"
      onmouseover="this.className='gui_array_head_open'"
      onmouseout="this.className='gui_array_head'">
    <span class="gui_array_key">Menü 2</span>
    <ul class="gui_array_list">
      <li class="gui_array_list">
        <a class="gui_array_value" href="2.html">Eintrag 2</a>
      </li>
      <li class="gui_array_head"
          onmouseover="this.className='gui_array_head_open'"
          onmouseout="this.className='gui_array_head'">
        <span class="gui_array_key">Submenü 2.1</span>
        <ul class="gui_array_list">
          <li class="gui_array_list">
            <a class="gui_array_value" href="2_1.html">Eintrag 2.1</a>
          </li>
          <li class="gui_array_list">
            <a class="gui_array_value" href="2_2.html">Eintrag 2.2</a>
          </li>
          <li class="gui_array_list">
            <a class="gui_array_value" href="2_3.html">Eintrag 2.3</a>
          </li>
        </ul>
      </li>
    </ul>
  </li>
  <li class="gui_array_list">
    <a class="gui_array_value" href="3.html">Link 2</a>
  </li>
</ul>

Das Attribut "onmouseover" dient hier zum Öffnen des Menüs und das Attribut "onmouseout" zum Schließen. Diese Attribute sind jedoch nicht zwingend erforderlich sondern dienen lediglich der Abwärtskompatibilität mit dem Internet Explorer und veralteten Browsern.

Wie kann ich Menüs automatisch erstellen lassen?

Mit der Template-Funktion "printUnorderedList" können Sie automatisch den Inhalt eines mehrdimensionales Arrays als Menü darstellen lassen.

Dazu sind 2 Schritte erforderlich. Zunächst legen Sie im PHP-Quellcode Ihres Plugins ein Array mit den Einträgen Ihres Menüs an. Danach lassen Sie sich im Template über den Aufruf der Funktion "printUnorderedList" das gewünschte Menü aus diesem Array generieren.

Gehen Sie wie folgt vor:

  1. Öffnen Sie die PHP-Datei mit dem Quellcode Ihres Plugins.
  2. Suchen Sie die Aktion, für welche das Menü angezeigt werden soll.
  3. Folgendes ist ein Beispiel für ein Array, welches Sie im PHP-Quellcode anlegen sollten:


Abbildung: Darstellung des Menüs

<?php
global $YANA;

$array = array(
  'ziel.html' => 'Link 1',
  'Menü 1' => array(
    '1.html' => 'Eintrag 1'
  ),
  'Menü 2' => array(
    '2.html' => 'Eintrag 2',
    'Submenü 2.1' => array(
      '2_1.html' => 'Eintrag 2.1',
      '2_2.html' => 'Eintrag 2.2',
      '2_3.html' => 'Eintrag 2.3' ),
  ),
  '3.html' => 'Link 2'
);

$YANA->setVar('myMenu', $array);
?>

Wie Sie sehen, enthalten Schlüssel des Arrays die URLs und die Werte enthalten die Beschriftung.

Um das eigentliche Menü generieren zu lassen, gehen Sie wie folgt vor:

  1. Öffnen Sie nun das HTML-Template, welches Sie für diese Aktion verwendet haben.
  2. Suchen Sie im HTML-Quellcode die Stelle, an welcher das Menü eingefügt werden soll.
  3. Fügen Sie den folgenden Quellcode ein:
[%printUnorderedList value=$myMenu keys_as_href="true" layout="2"%]

Dem Parameter "value" übergeben Sie das Array welches die Einträge des Menüs enthält. Über den Parameter "layout" können Sie zwischen dem 1. und 2. Layout wählen. Den Parameter "keys_as_href" sollten Sie auf den Wert "true" setzen.

Sonstige Funktionen

Wie rufe ich eine Aktion eines anderen Plugins auf?

Zum Bearbeiten von Aktionen bietet YANA die Funktion $YANA->handle(), welche bei Erfolg bool(true) und sonst bool(false) zurück gibt.

<?php
global $YANA;

/* Aktion "foo" aufrufen */
$bool = $YANA->handle("foo", $parameter);
if ($bool) {
    print "Die Aktion 'foo' wurde erfolgreich ausgeführt.";
} else {
    print "Der Aufruf von 'foo' hat einen Fehler erzeugt.";
}
?>

Wie leere ich den Template-Cache des Servers?

Dies bewirkt, dass alle Dateien im Verzeichnis "cache/" des Frameworks gelöscht werden.

<?php
global $YANA;

/* den Template-Cache des Servers leeren */
$YANA->handle("clear_server_cache", array());
?>

Wie erzeuge ich, z.Bsp. in einem Forum, eine Vorschau auf den Eintrag?

<!-- der folgende Eintrag im Template genügt: -->
<textarea id="eingabefeld" name="text"></textarea>
[%preview%]

Screenshot
Abbildung: Beispiel für die Darstellung im Browser

Wie erzeuge ich Microsummaries für Firefox 2.0 und höher?

"Microsummaries" sind "aktive Lesezeichen", dass heißt Links in den Bookmarks, deren Text sich dynamisch aktualisieren kann, wenn sich der Inhalt der Webseite ändert, auf die der Link verweist. Der Firefox-Browser bietet dem Nutzer automatisch die Verwendung von Microsummaries an, wenn dieser einen Bookmark einer Seite erzeugt, welche über dieses Feature verfügt.

Beispiele hierfür wären:

Weitere Varianten sind natürlich denkbar.

Microsummaries werden vom Yana Framework unterstützt. Sie werden mit Hilfe der Utility-Klasse "Microsummary" erzeugt. Im Folgenden einige Beispiele:

<?php
/* in einem Plugin ein Mircosummary erzeugen */
Microsummary::set($this->name, 'Text des Links');

/* Bitte beachten:
 * der erste Parameter ist eine Id, welche den Eintrag
 * eindeutig identifiziert.
 * Hier wird $this->name als Id verwendet,
 * weil der Name eines Plugins eindeutig sein sollte.
 * Es ist natürlich auch möglich einen anderen Text zu wählen,
 * Zum Beispiel um mehrere verschiedene Einträge pro Plugin
 * zu erzeugen.
 */

/* in einem Plugin ein Mircosummary lesen */
$microsummary = Microsummary::get($this->name);

/* in einem Plugin ein Mircosummary "veröffentlichen",
 * damit der Browser dieses beim Öffnen der Seite findet
 */
Microsummary::publish($this->name);

/* Aufruf der Microsummary im Browser */
index.php?action=get_microsummary&target=guestbook

/* Zum Testen muss die URL vervollständigt und im Browser in die Adresszeile eingegeben werden.
 * Das Argument "target" bezeichnet hier die Id der anzuzeigenden Microsummary.
 */
?>

Wie erzeuge ich RSS-Feeds?

"RSS-Feeds" sind elektronische, (meist) automatisch generierte und aktualisierte Verzeichnisse, welche verschiedene Informationen bereithalten können. Diese Verzeichnisse kann ein Besucher mit Programmen, die "RSS-Reader" genannt werden, lesen. In modernen Browsern ist diese Funktion bereits eingebaut, so dass der Besucher keine zusätzliche Software mehr benötigt.

Beispiele für RSS-Feeds:

Das Yana Framework unterstützt das Erzeugen von RSS-Feeds für Ihre Anwendungen. Dazu können Sie die für Sie vorbereiteten Klassen "RSS", bzw. "RSSitem" benutzen. Im Folgenden einige Beispiele.

<?php
/* Um in einem Plugin einen RSS-Feed zu erzeugen, legen Sie eine neue Funktion an.
   (Den Namen bitte Ihren Wünschen entsprechend ändern, er muss eindeutig sein.) */
function mein_rss_feed($ARGS)
{
    $rss = new RSS();
    // einen Titel und Beschreibung festlegen
    $rss->title = 'Max Muster\'s Neuigkeiten';
    $rss->description = 'das ist mein RSS-Feed zu meiner Homepage';
    // einen Eintrag erzeugen
    $item = new RSSitem();
    $item->title = '1. Eintrag';
    $item->link = 'http://beliebige.url';
    $item->description = 'Ein kurzer Text, welcher den Inhalt beschreibt, oder ein Textauszug.';
    // den Eintrag zum RSS-Feed hinzufügen
    $rss->addItem($item);
    // ein 2. Eintrag
    $item = new RSSitem();
    $item->title = 'noch ein Eintrag';
    $item->link = 'http://beliebige.andere.url';
    $item->description = 'zweite Beschreibung';
    $rss->addItem($item);
    // so geben Sie den RSS-Feed an den Browser aus
    print utf8_encode($rss->toString());
    exit(0);
}

/* Sie können einen Link auf Ihren RSS-Feed in der Anwendung anzeigen lassen.
   Dazu benutzen Sie die Funktion RSS::publish() und den Namen der Funktion,
   welche Ihren RSS-Feed erzeugt.
   Tipp: Am Einfachsten ist es, den Link über den Konstruktor Ihres Plugins
   einzubinden.*/
function plugin_mein_test($name)
{
    RSS::publish('mein_rss_feed');
    // hier kann weiterer Quellcode folgen
}
?>

Tutorials

mein erstes Plugin

Kapitel 1: Vorbereitung

Das folgende Tutorial wird demonstrieren, wie Sie eigene Plugins für das Yana Framework schreiben können. Dazu wird im Verlauf des Textes ein einfaches Plugin zum Schreiben von so genannten "Blogs" erstellt. Den Quellcode finden Sie als Anhang am Ende dieses Tutorials.

Der Zeitaufwand um alle Schritte nachzuvollziehen beläuft sich auf etwa 1 Stunde. Literaturhinweise zu thematisch verwandten Artikeln finden Sie jeweils am Ende eines Abschnitts. Falls Sie einen Abschnitt überspringen wollen, finden Sie zudem fertige Quellcodeauszüge, welche Sie kopieren können.

Bevor Sie mit diesem Tutorial beginnen, sollten Sie sicherstellen, dass Sie einige Vorbereitungen abgeschlossen haben, da Sie andernfalls an eine Stelle gelangen könnten, an der Sie das Tutorial nicht fortsetzen können.

Zunächst benötigen Sie Zugang zu einem Webserver mit PHP. Vorzugsweise sollte dies eine lokale Installation sein, da dadurch die Arbeit vereinfacht wird. Allerdings genügt auch ein Zugang zu einem Webserver via FTP.

Außerdem sollten Sie vorab das Yana Framework bereits installiert haben und als Administrator darauf zugreifen können. Sie müssen außerdem das "Software Development Kit" für das Yana Framework installiert und aktiviert haben.

Optional empfehle ich Ihnen, einen geeigneten Editor für das Framework, wahlweise die Software " PSPad " oder alternativ " ConTEXT ", zu installieren. Für diese beiden Editoren stehen Syntax-Highlighter und Code-Templates zur Verfügung. Lesen Sie vorab das Kapitel über Editoren, falls Sie eine Installationsanleitung wünschen. Für den Zweck dieses Tutorials, wird die Software "PSPad" verwendet.

Grundlegende Kenntnisse im Aufbau und der Funktion von PHP und MySQL-Datenbanken werden vorausgesetzt.

Kapitel 2: Erstellen der Datenbank

Datenbanken werden im Yana Framework repräsentiert durch so genannte "Datenbankschemata". Diese Schemata sind Beschreibungen der Struktur einer Datenbank. Das heißt, der enthaltenen Tabellen, deren Spalten, Indexes und Constraints. Diese Informationen werden in Dateien gespeichert. Diese Dateien werden "Datenbankstrukturdateien" genannt und im Verzeichnis "config/db" des Frameworks abgelegt.

Darüber hinaus - und das unterscheidet das Yana Framework grundlegend von anderen Frameworks - enthalten diese Dateien auch die Beschreibung der Semantik einer Datenbank. Das heißt, in welchem Kontext eine Spalte sichtbar oder unsichtbar sein sollte, wie die Informationen für den Nutzer dargestellt werden sollen oder welche Beschriftung die Spalte haben sollte.

Sie benötigen zum Erstellen einer Datenbank für das Yana Framework also kein teures Modellierungswerkzeug und keine SQL-Kenntnisse, sondern lediglich einen einfachen Texteditor.

Um eine neue Datenbank zu erzeugen, öffnen Sie zunächst eine leere Textdatei in PSPad. Stellen die Syntax der Datei auf "Yana Framework" um (sollten Sie den Highlighter und die Code-Templates noch nicht installiert haben, lesen Sie dazu das Kapitel "Editoren für das Yana Framework" ).

Die neue Datenbank wird eine Tabelle "blog" enthalten, welche die Einträge eines Weblogs speichern soll. Jeder Eintrag wird eine eindeutige Id (Primärschlüssel) besitzen, den Namen des Autors, Datum der Erstellung, einen Titel und einen Text.

Bei der Erstellung der Datenbank können Ihnen Code-Templates helfen. Geben Sie den Text "db" ein und drücken Sie die Tasten <STRG> + <SPACE> gleichzeitig. Dadurch wird die Liste der Vorlagen geöffnet. Diese Liste hat zwei Spalten: links in Fettdruck ein "Shortcut", den Sie eingeben können um das Template direkt aufzurufen (wie in diesem Fall "db") und rechts eine Beschreibung des Templates.

Screenshot
Abbildung: Einfügen von Code-Templates

Wählen Sie die Vorlage "database definition" und drücken Sie <ENTER>. Das Dokument sollte nun so aussehen wie in folgender Abbildung:

Screenshot
Abbildung: Rumpf der Datenbank

Fügen Sie nun eine Tabelle ein. Drücken Sie dazu <STRG> + <SPACE> und wählen Sie den Eintrag "table definition" (Shortcut "tbl"). Benennen Sie die Tabelle indem Sie den Tabellennamen als Bezeichnung des öffnenden und schließenden Tags einsetzen. In diesem Tutorial soll die Tabelle den Namen "blog" erhalten.

Screenshot
Abbildung: Tabelle "blog"

Fügen Sie der Tabelle nun einen Primärschlüssel hinzu. Eine Tabelle kann stets nur 1 Primärschlüssel besitzen. Der Primärschlüssel muss stets aus genau einer Spalte bestehen und diese Spalte muss vom Typ "integer", "float" oder "string" sein. So genannte "compound primary keys" werden nicht unterstützt.

Um eine Spalte hinzuzufügen, klicken Sie in den Container "CONTENT" der Tabelle und fügen Sie das Code Template "primary key" ein (Shortcut "id"). Nennen Sie die Spalte "blog_id".

Um zu definieren, dass die Spalte "blog_id" ein Primärschlüssel ist, müssen Sie den Namen der Spalte im Feld "PRIMARY_KEY" eintragen.

Haben Sie diese Schritte erfolgreich durchgeführt, sollte Ihre Datei wie folgt aussehen:

Screenshot
Abbildung: Einfügen des Primärschlüssels

Auf die gleiche Weise fügen Sie nun noch eine Spalte vom Typ "string" für den Titel ein, eine Spalte vom Typ "text" für den Text des Eintrags. Eine Spalte vom Typ "time" für das Erstellungsdatum und eine weitere Spalte vom Typ "string" für den Namen des Autors.

Der Quellcode sollte nun wie folgt aussehen:

<USE_STRICT>true</USE_STRICT>
<READONLY>false</READONLY>
<TABLES>
	<blog>
		<PRIMARY_KEY>blog_id</PRIMARY_KEY>
		<CONTENT>
			<blog_id>
				<TYPE>integer</TYPE>
				<LENGTH>8</LENGTH>
				<REQUIRED>AUTO</REQUIRED>
				<DISPLAY>
					<HIDDEN>true</HIDDEN>
				</DISPLAY>
			</blog_id>
			<blog_title>
				<TYPE>string</TYPE>
				<LENGTH>255</LENGTH>
				<DESCRIPTION>Titel</DESCRIPTION>
			</blog_title>
			<blog_text>
				<TYPE>text</TYPE>
				<LENGTH>3000</LENGTH>
				<REQUIRED>true</REQUIRED>
				<DESCRIPTION>Text</DESCRIPTION>
			</blog_text>
			<blog_created>
				<TYPE>time</TYPE>
				<REQUIRED>AUTO</REQUIRED>
				<DESCRIPTION>Datum</DESCRIPTION>
			</blog_created>
			<blog_author>
				<TYPE>string</TYPE>
				<LENGTH>255</LENGTH>
				<DESCRIPTION>Autor</DESCRIPTION>
			</blog_author>
		</CONTENT>
	</blog>
</TABLES>

Vergleichen Sie den obigen Quellcode mit Ihrem Ergebnis.

Einführung in die wichtigsten Eigenschaften einer Tabellenspalte

Die Eigenschaft " TYPE " gibt den Typ der Spalte an, " DESCRIPTION " eine Beschriftung der Spalte für den Nutzer. Die Eigenschaft "LENGTH" gibt an wie groß der Inhalt für das Feld sein darf. Bei Spalten vom Typ "string" (in MySQL werden diese als "VARCHAR" umgesetzt) ist dies die Anzahl der Zeichen, welche der Eintrag maximal lang sein darf.

Die Eigenschaft " REQUIRED " gibt an, ob ein Wert zwingend erforderlich ist. Sie kann drei Werte annehmen: "true", "false" und "AUTO". Dabei bedeutet: "true" = ein Pflichtfeld, "false" = eine optionale Angabe und "AUTO" = falls der Nutzer keine Angaben macht, wird der Wert automatisch erzeugt.

Oder anders formuliert: die  Eigenschaft "REQUIRED" gibt an, ob eine Spalte "Nullable" ist. Hat "REQUIRED" den Wert "true", wird die Spalte in MySQL zu "NOT NULL" umgesetzt und umgekehrt.

Wenn Sie zum Beispiel den Wert "AUTO" auf eine Spalte vom Typ "integer" anwenden, so erhalten Sie in MySQL eine Spalte, welche das Autoinkrementfeature verwendet. Die Spalte "blog_id" in obigem Beispiel ist somit eine Spalte mit Autoinkrement. (In MSSQL und DB2 wird dies als "Identity", als "Sequenz" in PostgreSQL und in Oracle als Trigger realisiert). Der Wert "AUTO" auf einer Spalte vom Typ "time" bewirkt, dass die aktuelle Zeit als Wert eingetragen wird.

Eine Eigenschaft, welche Sie in dem obigen Beispiel bisher noch nicht verwendet haben, heißt " DEFAULT ". Diese kann verwendet werden, um einen "Defaultwert" anzugeben, welcher automatisch verwendet werden soll, falls der Nutzer keine anderen Angaben macht.

Zum Abschluss, die Eigenschaft " DISPLAY ". Diese Eigenschaft hat keine Entsprechung in SQL. Sie dient der Steuerung der Darstellung der Spalte im Framework. Sie gibt an, in welchen Formularen die Spalte: sichtbar, sichtbar und editierbar, oder nicht sichtbar sein soll. Dabei wird unterschieden zwischen Formularen zum: Anzeigen, Suchen, Erstellen und Editieren von Datensätzen in der Tabelle.

Verfeinern der Angaben

Die obige Tabelle sollte noch um einige Angaben ergänzt werden.

Beispielsweise sollte festgelegt werden, dass die Spalten "blog_title" (Titel) und "blog_text" (Text) immer ausgefüllt werden müssen. Dazu ergänzen Sie die Eigenschaft "REQUIRED" mit dem Wert "true" (Shortcut "req").

Die Angabe zum Erstellungsdatum wird automatisch eingefügt. Sie sollte daher beim Schreiben des Eintrags für den Nutzer nicht sichtbar sein und nicht nachträglich editiert werden können. Fügen Sie für die Spalte "blog_created" (Datum) eine Eigenschaft "DISPLAY" ein (Shortcut "disp"). Setzen Sie die Werte "HIDDEN.NEW" und "READONLY.EDIT" auf "true". Setzen Sie alle anderen Werte auf "false".

Mehrere Blogs in einer Tabelle

Sie können selbstverständlich mehrere Blogs in einer Tabelle speichern. Dazu benötigen Sie eine zusätzliche Spalte, welche identifiziert, zu welchem Blog ein Eintrag gehört. Dies kann zum Beispiel nützlich sein, falls Sie mehrere Webseiten haben und pro Webseite einen eigenen Blog speichern möchten.

Die Unterscheidung in mehrere Blogs und die Zuordnung zu einzelnen Webseiten müssen Sie nicht von Hand programmieren. Das Framework besitzt für diesen Zweck ein vorbereitetes Template.

Fügen Sie zunächst eine neue Spalte vom Typ "profile" ein (Shortcut "pid"). Die Spalte sollte den Namen "profile_id" haben. Anschließend fügen Sie für die Tabelle, unter der Eigenschaft "PRIMARY_KEY" die Eigenschaft "PROFILE_KEY" ein (Shortcut "prf") und setzen den Wert dieser Eigenschaft auf den Namen der Spalte: "profile_id".

Vergleichen Sie Ihr Ergebnis mit dem folgenden Quellcode.

<USE_STRICT>true</USE_STRICT>
<READONLY>false</READONLY>
<TABLES>
	<blog>
		<PRIMARY_KEY>blog_id</PRIMARY_KEY>
		<PROFILE_KEY>profile_id</PROFILE_KEY>
		<CONTENT>
			<blog_id>
				<TYPE>integer</TYPE>
				<LENGTH>8</LENGTH>
				<REQUIRED>AUTO</REQUIRED>
				<DISPLAY>
					<HIDDEN>true</HIDDEN>
				</DISPLAY>
			</blog_id>
			<blog_title>
				<TYPE>string</TYPE>
				<LENGTH>255</LENGTH>
				<DESCRIPTION>Titel</DESCRIPTION>
				<REQUIRED>true</REQUIRED>
			</blog_title>
			<blog_text>
				<TYPE>text</TYPE>
				<LENGTH>3000</LENGTH>
				<REQUIRED>true</REQUIRED>
				<DESCRIPTION>Text</DESCRIPTION>
				<REQUIRED>true</REQUIRED>
			</blog_text>
			<blog_created>
				<TYPE>time</TYPE>
				<REQUIRED>AUTO</REQUIRED>
				<DESCRIPTION>Datum</DESCRIPTION>
				<DISPLAY>
  					<HIDDEN>
  						<NEW>true</NEW>
  					</HIDDEN>
  					<READONLY>
  						<EDIT>true</EDIT>
  					</READONLY>
  				</DISPLAY>
			</blog_created>
			<blog_author>
				<TYPE>string</TYPE>
				<LENGTH>255</LENGTH>
				<DESCRIPTION>Autor</DESCRIPTION>
			</blog_author>
			<profile_id>
				<TYPE>profile</TYPE>
				<LENGTH>128</LENGTH>
				<REQUIRED>AUTO</REQUIRED>
				<DISPLAY>
					<HIDDEN>true</HIDDEN>
				</DISPLAY>
			</profile_id>
		</CONTENT>
	</blog>
</TABLES>

Damit ist das Erstellen der Datenbank abgeschlossen. Speichern Sie Ihre Änderungen unter der Datei "blog.config" und schließen Sie das Programm.

Literaturhinweise

Falls Sie sich tiefer mit den in diesem Abschnitt behandelten Themen beschäftigen wollen, finden Sie Anleitung in folgenden Artikeln:

Der folgende Abschnitt wird sich mit der Erstellung des Programmcodes beschäftigen.

Kapitel 3: Erstellen eines neuen Plugins

Sofern Sie das Tutorial bis zu diesem Punkt nachvollzogen haben, besitzen Sie zu diesem Zeitpunkt bereits eine einfache Datenbank. Um diese jedoch "zum Leben zu erwecken", fehlt Ihnen noch die Business-Logik der eigentlichen Anwendung, sowie eine Oberfläche zur Darstellung von Formularen und Nutzereingaben. Beides werden Sie im folgenden Abschnitt erstellen.

Öffnen Sie nun die Startseite des Yana Frameworks in einem javascriptfähigen Webbrowser, beispielsweise Firefox 2.0. Melden Sie sich über den Link "Login" am System als "Administrator" an. Sie werden Administratorrechte benötigen, um mit dem nächsten Schritt fortfahren zu können.

Öffnen Sie auf der Startseite des Frameworks den Link "Software Development Kit". Sollten Sie dieses bis jetzt noch nicht installiert, bzw. aktiviert haben, holen Sie dies bitte jetzt nach. Lesen Sie dazu das Kapitel "Plugins und Anwendungen erstellen".

Haben Sie den Link geöffnet, sollten Sie folgendes Formular sehen können.

Screenshot
Abbildung: Startseite des "Software Development Kit"

Zunächst können Sie einen Namen (zum Beispiel "mein Blog"), eine beliebige Beschreibung und ein Logo für Ihr Plugin auswählen. Unter der Registerkarte "Autor" können Sie Angaben zu Ihrem Namen, Ihrer Webseite und Kontaktadresse machen.

Auf der Seite "sonstige Daten" können Sie den "Typ der Anwendung" auf den Wert "primary" ändern. Dadurch wird das Plugin als "Hauptprogramm" deklariert. Diese Angabe ist optional und keine Pflicht, kann jedoch die Performance erhöhen.

Screenshot
Abbildung: Setzen des Typs der Anwendung

Klicken Sie anschließend direkt auf die Registerkarte "Datenbank".

Screenshot
Abbildung: Auswählen der Datenbankstrukturdatei

Klicken Sie auf die Schaltfläche "Durchsuchen". Wählen Sie als Quelle die von Ihnen erstellte Datei "blog.config" aus.

Weitere Angaben zu Ihrem Plugin sind an dieser Stelle nicht erforderlich. Klicken Sie auf die Schaltfläche "Fertigstellen", um den Quellcode und die Eingabeoberflächen für Ihr erstes Plugin generieren zu lassen. Anschließend können Sie das gerade erstellte Plugin sofort ausprobieren.

Das neue Plugin ausprobieren

Öffnen Sie das Administrationsmenü im Expertenmodus. Klicken Sie im Menü "Plugins" auf den Link "Liste neu laden". Anschließend wählen Sie aus der Liste der Plugins den Namen Ihres Plugins aus und aktivieren Sie dieses durch anklicken der Checkbox links neben dem Namen. Klicken Sie auf die Schalfläche "Änderungen speichern" unterhalb des Menüs.

Zum Vergleich zeigt die folgende Abbildung das oben genannte Menü.

Screenshot
Abbildung: Aktivieren des Plugins

Hinweise für Nutzer mit Datenbankunterstützung

Achtung:

Achtung! Falls Sie die Datenbankunterstützung NICHT aktiviert haben, müssen Sie diesen Schritt NICHT durchführen.
Falls Sie die Datenbankunterstützung aktiviert haben und beispielsweise eine MySQL-Datenbank zum Speichern der Einträge benutzen, dann müssen Sie die Tabellen für das Plugin zuerst installieren. Öffnen Sie dazu das Menü "Datenbank Setup" und wählen Sie aus dem Dropdownmenü den Eintrag "markierte Datenbanken installieren". Es erscheint eine Auswahlliste. Aktivieren Sie nur den Eintrag der Datenbank Ihres Plugins und klicken Sie auf die Schaltfläche "Änderungen speichern".

Siehe folgende Abbildung:

Screenshot
Abbildung: die Tabelle des Plugins auf der Datenbank installieren

Anschließend wechseln Sie zurück auf die Sitemap des Frameworks. Dort sollte nun der Name Ihres Plugins im Auswahlmenü auftauchen. Klicken Sie auf diesen Link. Sie sollten nun die Startseite Ihrer Anwendung sehen, wie die folgende Abbildung zeigt.

Screenshot
Abbildung: Startseite des neuen Plugins

Der Text "keine Einträge gefunden" zeigt an, dass zur Zeit keine Einträge in Ihrem Blog gespeichert sind. Klicken Sie auf den Link "new" um einen neuen Eintrag zu erstellen.

Screenshot
Abbildung: Erstellen eines neuen Eintrags

Anschließend sollte Ihnen folgende Übersichtsseite angezeigt werden. (Die Abbildung zeigt das Formular mit zwei Einträgen)

Screenshot
Abbildung: Übersichtsdarstellung

Es gibt weitere, alternative Ansichten. Am Ende der Tabelle finden Sie eine Liste mit 4 verschiedenen Layouts. Sie können sich entscheiden, welche Darstellung Ihnen besser gefällt.

Screenshot
Abbildung: Detaildarstellung

Klicken Sie auf den Link "bearbeiten" um Einträge zu editieren. Sie sollten das folgende Formular angezeigt bekommen.

Screenshot
Abbildung: Editieren von Einträgen

Hinweise zur Bedienung des Editors

Durch Anklicken der Spalten, ändern Sie die Sortierung. Zeilen, die Sie ändern möchten, markieren Sie in der linken Spalte durch Anklicken der Checkbox. In der letzten Zeile befinden sich leere Felder, welche Sie benutzen können um schnell einen neuen Eintrag zu erstellen.

Dieses Formular verfügt über ein besonderes Feature. Wenn Sie aus dem Menü "Einträge pro Seite" den Wert "1" wählen, vergrößert sich die Ansicht des Editors für den jeweiligen Eintrag, was größeren Komfort bei der Eingabe der Daten ermöglicht, wie die folgende Abbildung zeigt.

Screenshot
Abbildung: Editieren eines einzelnen Eintrags

Falls Sie dies wünschen, können Sie die weiteren Funktionen Ihres neuen Plugins an dieser Stelle ebenfalls probieren.

Literaturhinweise
Falls Sie sich tiefer mit den in diesem Abschnitt behandelten Themen beschäftigen wollen, finden Sie Anleitung in folgenden Artikeln:

Wie Sie sehen konnten, hat das Yana Framework Ihnen bereits einen großen Teil der notwendigen Arbeiten abgenommen. Allerdings gibt es sicher einige Details, welche Sie nachträglich Ihren Bedürfnissen anpassen möchten. Mit diesen Anpassungen wird sich der folgende Abschnitt des Tutorials beschäftigen.

Kapitel 4: Editieren von Templates und Konfigurationsdateien

Im folgenden Abschnitt werden die Definitionsdatei von Plugins und Templates vorgestellt. Es wird demonstriert, wie diese Dateien editiert werden können, um sie persönlichen Bedürfnissen anzupassen.

Einfügen von Smilies und embedded Tags

Als ersten Schritt soll demonstriert werden, wie Sie Smilies (Emoticons) und embedded Tags (zum Formatieren von Text) einfügen können. Öffnen Sie dazu die Datei "skins/default/blog/blog_default_new_blog.html" in PSPad. Beachten Sie dabei, dass Sie den Text "blog" durch den Namen Ihres Projektes ersetzen müssen. Wählen Sie den Highlighter "Yana Framework Templates" aus der Liste der verfügbaren Highlighter.

Zum Vergleich dazu siehe auch die folgende Abbildung:

Screenshot
Abbildung: Darstellung des Templates in PSPad

Der Aufruf der Funktion "import" lädt das Baummenü aus der Datei "index.html". Die Funktion "create" ruft den Formulargenerator des Yana Frameworks auf, um das Formular zum Erzeugen eines neuen Eintrags zu generieren.

Eine Erläuterung der Funktion "create" finden Sie in der Referenz der Template-Funktionen und -Modifier.

Auch in Templates können Sie wiederum Code-Templates verwenden. Fügen Sie nun hinter dem Funktionsaufruf "create" einen Aufruf der Funktion "embeddedTags" (Shortcut "embTag"). Argumente brauchen Sie für diese Funktion zunächst nicht angeben.

Eine Erläuterung der Funktion "embeddedTags" finden Sie in der Referenz der Template-Funktionen und -Modifier.

Der Quellcode sollte nun wie folgt aussehen:

<!-- Begin: menu -->
<div style="width: 250px; overflow: auto; float: left;">
[%import file="index.html"%]
</div>
<!-- End: menu -->
<!-- Begin: content -->
<div style="margin-left: 260px;">
[%create
  template="new"
  file="blog"
  table="blog"
  where=$WHERE
  titles=""
  on_edit="blog_write_edit_blog"
  on_delete="blog_write_delete_blog"
  on_new="blog_write_new_blog"
  on_search="blog_read_search_blog"
  on_download="blog_blog_download"
  sort=$SORT
  desc=$DESC
  page=$PAGE
  entries=$ENTRIES %]
[%embeddedTags%]
</div>
<!-- End: content -->
<!-- Begin: foot -->
<div style="clear: both;">
&nbsp;
<!-- your text here -->
</div>
<!-- End: foot -->

Vergleichen Sie den obigen Quellcode mit Ihrem Ergebnis.

Wenn Sie die Seite Ihres Plugins nun erneut im Browser aufrufen, präsentiert diese sich wie folgt.

Screenshot
Abbildung: Darstellung im Browser (Firefox 3)

Es ist angebracht, diese Darstellung optisch anzupassen. Da es dafür verschiedene Lösungen gibt und Geschmäcker bekanntlich verschieden sind, dazu folgender Vorschlag.


  <fieldset>
    <legend style="font-size: 12px; font-weight: bold;">Text formatieren:</legend>
    [%embeddedTags show="b,i,u,|,h,emp,code,hide,|,small,big,|,img,url,mail,-,mark,color,smilies"%]
  </fieldset>

Falls die Tags "fieldset" und "legend" Ihnen bis jetzt noch nicht vertraut waren: Diese Tags erzeugen Unterabschnitte innerhalb von Formularen. Der Tag "legend" legt eine Beschriftung fest. Dargestellt werden "Fieldsets" standardmäßig als umrahmte Blockabschnitte. Der Text innerhalb des Tags "Legend" wird dabei innerhalb der Umrandung dargestellt.
Zudem demonstriert dieser Quellcode die Verwendung der Argumente der Funktion "embeddedTags". Achten Sie besonders auf das Argument "show" der Funktion "embeddedTags". Diese akzeptiert die beiden besonderen Werte "|" und "-". Dabei erzeugt "|" einen senkrechten Trennstrich und "-" kann verwendet werden, um einen Zeilenumbruch zu erzeugen.

Abschließend soll oberhalb der beiden Fieldsets eine Vorschau auf den neuen Blogeintrag erzeugt werden (verwenden Sie dazu den Shortcut "preview"). Sie können das Template übernehmen, die Parameter "height" und "width" werden nicht benötigt und können entfernt werden.

Der daraus resultierende Quellcode sieht wie folgt aus:


<!-- Begin: menu -->
<div style="width: 250px; overflow: auto; float: left;">
[%import file="index.html"%]
</div>
<!-- End: menu -->
<!-- Begin: content -->
<div style="margin-left: 260px;">
[%create
  template="new"
  file="blog"
  table="blog"
  where=$WHERE
  titles=""
  on_edit="blog_write_edit_blog"
  on_delete="blog_write_delete_blog"
  on_new="blog_write_new_blog"
  on_search="blog_read_search_blog"
  on_download="blog_blog_download"
  sort=$SORT
  desc=$DESC
  page=$PAGE
  entries=$ENTRIES %]
  [%preview%]
  <fieldset>
    <legend style="font-size: 12px; font-weight: bold;">Text formatieren:</legend>
    [%embeddedTags show="b,i,u,|,h,emp,code,hide,|,small,big,|,img,url,mail,-,mark,color,smilies"%]
  </fieldset>
</div>
<!-- End: content -->
<!-- Begin: foot -->
<div style="clear: both;">
&nbsp;
<!-- your text here -->
</div>
<!-- End: foot -->

Als Quelle verwendet die Vorschau automatisch das zuletzt aktivierte Textarea-Feld der Seite. Die Darstellung wird via AJAX vom Server geholt und direkt angezeigt, ohne das Formular neu laden zu müssen.

Im Browser präsentiert sich das Ergebnis wie folgt:

Screenshot
Abbildung: Darstellung im Browser (Firefox 3)

Ändern der Sortierreihenfolge

Klicken Sie noch einmal auf den Menüpunkt "anzeigen". Beachten Sie die Reihenfolge der Einträge. Per Voreinstellung sind diese aufsteigend nach dem Primärschlüssel sortiert. Dies ist für einen Blog in der Regel nicht erwünscht. Stattdessen sollten die Einträge absteigend nach dem Datum ihrer Erstellung sortiert sein. Um dies zu korrigieren, öffnen Sie nun die Datei "skins/default/blog/blog_read_read_blog.html" in PSPad. Beachten Sie dabei, dass Sie den Text "blog" durch den Namen Ihres Projektes ersetzen müssen. Wählen Sie den Highlighter "Yana Framework Templates" aus der Liste der verfügbaren Highlighter.

Wie bereits erwähnt, dient die Funktion "create" zum Aufrufen des Formulargenerators. Dieser nimmt einige Parameter, mit welchen die Ausgabe gesteuert wird. Setzen Sie den Parameter "sort" auf "blog_created" um nach der Spalte "blog_created" der Tabelle "blog" zu sortieren, welche das Datum der Erstellung der Einträge enthält. Setzen Sie den Parameter "desc" auf den Wert "true", was bewirkt, dass absteigend (eng. "descending") sortiert wird.

Beachten Sie, dass der Parameter "where" auf die Variable "$WHERE" gesetzt ist. Dies wird zu einem späteren Abschnitt dieses Tutorials eine wichtige Rolle spielen.

Der folgende Quellcodeauszug illustriert das Ergebnis.

<!-- Begin: menu -->
<div style="width: 250px; overflow: auto; float: left;">
[%import file="index.html"%]
</div>
<!-- End: menu -->
<!-- Begin: content -->
<div style="margin-left: 260px;">
[%create
  template="view"
  layout=3
  file="blog"
  table="blog"
  where=$WHERE
  titles=""
  on_edit="blog_write_edit_blog"
  on_delete="blog_write_delete_blog"
  on_new="blog_write_new_blog"
  on_search="blog_read_search_blog"
  on_download="blog_blog_download"
  sort="blog_created"
  desc=$DESC
  page=$PAGE
  entries=$ENTRIES %]
</div>
<!-- End: content -->
<!-- Begin: foot -->
<div style="clear: both;">
&nbsp;
<!-- your text here -->
</div>
<!-- End: foot -->

Vergleichen Sie den obigen Quellcode mit Ihrem Ergebnis.

Editieren der Einträge des Baummenüs

Als nächstes soll das Baummenü so angepasst werden, dass die Einträge "neu" und "Über dieses Plugin ..." nur Nutzern angezeigt werden, die am System angemeldet sind und über ein ausreichend hohes Sicherheitslevel verfügen. Außerdem möchten Sie möglicherweise die Beschriftung der Optionen ändern.

Der Quellcode der Datei sieht zunächst wie folgt aus:

<ul class="menu root" id="_menu">
  <li class="menu">
    <div onclick="yanaMenu(this)">blog</div>
    <ul class="menu">
<!-- [%if $PERMISSION >= 75%] -->
      <li class="entry"><a href=[%"action=mein_plugin_read_edit_blog"|href%]>[%$LANGUAGE.MENU.EDIT%]</a></li>
<!-- [%/if%] -->
<!-- [%if $PERMISSION >= 0%] -->
      <li class="entry"><a href=[%"action=mein_plugin_default_new_blog"|href%]>[%$LANGUAGE.MENU.NEW%]</a></li>
<!-- [%/if%] -->
<!-- [%if $PERMISSION >= 0%] -->
      <li class="entry"><a href=[%"action=mein_plugin_read_search_blog"|href%]>[%$LANGUAGE.MENU.SEARCH%]</a></li>
<!-- [%/if%] -->
<!-- [%if $PERMISSION >= 0%] -->
      <li class="entry"><a href=[%"action=mein_plugin_read_read_blog"|href%]>[%$LANGUAGE.MENU.VIEW%]</a></li>
<!-- [%/if%] -->
    </ul>
  </li>
  <li class="entry"><a href=[%"action=about&target=mein_plugin&type=plugin"|href%]>[%$LANGUAGE.ABOUT%] ...</a></li>
</ul>

Dass die IF-Verzweigungen hier in Kommentare eingebettet sind dient der besseren Lesbarkeit des Codes und der Darstellung des Templates im Browser. Für das Template selbst macht es keinen Unterschied, ob Sie diese Kommentare verwenden wollen oder nicht.

Die Variable $PERMISSION enthält die Sicherheitsstufe Ihres Besuchers. Gäste erhalten in der Voreinstellung automatisch die Sicherheitsstufe "0", Administratoren die Stufe "100". Dazwischen können weitere Stufen vergeben werden. Voreingestellt ist für Moderatoren beispielsweise die Stufe "30". Sie können diese Variable verwenden um zu entscheiden, wann bestimmte Menüpunkte angezeigt werden sollen und wann nicht. Ändern Sie den Wert für "Permission" für die Optionen "new" und "about" beispielsweise auf ">= 30" (der Wert 30 steht per Default für die Gruppe der Moderatoren).

Da die Variable $PERMISSION stets einen Wert >= 0 hat, können Sie die entsprechenden Prüfungen zum Zweck besserer Performance auch entfernen.

Vergleichen Sie Ihr Ergebnis mit dem folgenden Code.

<ul class="menu root" id="_menu">
  <li class="menu">
    <div onclick="yanaMenu(this)">blog</div>
    <ul class="menu">
<!-- [%if $PERMISSION >= 75%] -->
      <li class="entry"><a href=[%"action=mein_plugin_read_edit_blog"|href%]>[%$LANGUAGE.MENU.EDIT%]</a></li>
<!-- [%/if%] -->
<!-- [%if $PERMISSION >= 30%] -->
      <li class="entry"><a href=[%"action=mein_plugin_default_new_blog"|href%]>[%$LANGUAGE.MENU.NEW%]</a></li>
<!-- [%/if%] -->
      <li class="entry"><a href=[%"action=mein_plugin_read_search_blog"|href%]>[%$LANGUAGE.MENU.SEARCH%]</a></li>
      <li class="entry"><a href=[%"action=mein_plugin_read_read_blog"|href%]>[%$LANGUAGE.MENU.VIEW%]</a></li>
    </ul>
  </li>
  <li class="entry"><a href=[%"action=about&target=mein_plugin&type=plugin"|href%]>[%$LANGUAGE.ABOUT%] ...</a></li>
</ul>
Anpassen der Konfigurationsdateien

Wie Sie vielleicht bereits vermutet haben, war dies lediglich der erste Schritt. Zwar ist der Menüpunkt zum Anlegen eines neuen Eintrags nun für Gäste ausgeblendet, allerdings ist er durch Eingabe der richtigen URL in die Adresszeile des Browsers immer noch aufrufbar. Ein geschickter Nutzer könnte sich diesen Umstand zunutze machen, um die Prüfung seines Sicherheitslevels zu umgehen. Der folgende Abschnitt wird demonstrieren, wie Sie die Konfigurationsdatei Ihres Plugins editieren können, um dies zu verhindern.

Von HTML-Templates nun zurück zu Konfigurationsdateien. Öffnen Sie die Datei "plugins/blog.config" in PSPad (beachten Sie, dass sie den Namen "blog" durch den Namen Ihres Plugins ersetzen müssen). Wählen Sie den Highlighter "Yana Framework" aus.

Screenshot
Abbildung: Darstellung der Konfigurationsdatei in PSPad

Der Container "INFO" enthält den Header der Konfigurationsdatei. Dieser Block kann, je nachdem welche Eingaben beim Erstellen des Plugins gemacht wurden, in Ihrem Fall geringfügig anders aussehen.

Zunächst einmal sehen Sie hier unter dem Eintrag "START" die gewählte Startseite des Plugins (blog_read_read_blog). Ihr Wert entspricht dem Wert des Arguments "action", welches an die URL angehängt wird. Der Wert identifiziert eindeutig das Plugin und die Aktion, welche das Plugin ausführen soll. Der Name wurde automatisch generiert. Falls Sie eine andere Seite als Startseite wünschen, rufen Sie die diese Seite in Ihrem Browser auf. Schauen Sie in der Adressleiste des Browsers nach dem Wert des Arguments "action" und kopieren Sie diesen Wert aus der Adressleiste in das Feld "START".

Der Container "INTERFACE" beschreibt alle Aktionen, welche Ihr Plugin verarbeiten kann. Für jede Aktion existiert ein Tag, welcher weitere Tags enthält, welche dessen Eigenschaften beschreiben. Die Namen wurden auch hier automatisch erstellt. Beachten Sie, dass diese Namen eindeutig sein müssen. Es ist folglich nicht sinnvoll, eine Aktion beispielsweise "insert" zu nennen, weil diese Bezeichnung vermutlich nicht eindeutig wäre.

Eine Erläuterung aller Tags dieser Konfigurationsdatei, sowie Codebeispiele, finden Sie im Kochbuch für Entwickler, Kapitel "Plugins editieren".

Im nächsten Schritt werden die Änderungen in der Datei "index.html" in der Konfigurationsdatei nachvollzogen, um ein Umgehen der Sicherheitsprüfung unmöglich zu machen.

Suchen Sie dazu zunächst in dem Dokument die Aktion "blog_default_new_blog" und setzen Sie im Feld "PERMISSION" den Wert auf "30", analog zur Datei "index.html". Wiederholen Sie dies für die Aktion "blog_write_new_blog". Zum Verständnis: Die Aktion "blog_default_new_blog" dient dem Anzeigen des Formulars, die Aktion "blog_write_new_blog" dient dem Speichern der Eingaben. Beide Aktionen gehören somit zum gleichen Formular und beide Werte müssen daher entsprechend geändert werden.

In der Datei "index.html" war die Option "list" enthalten, welche entfernt wurde (vergleichen Sie mit dem obigen Quellcode ). Diese Option war verbunden mit der Aktion "blog_read_read_blog". Suchen Sie nun diese Aktion und entfernen Sie diese.

Der Container "INTERFACE" sollte nun den folgenden Inhalt haben.

<INTERFACE>
	<BLOG_READ_EDIT_BLOG>
		<TYPE>read</TYPE>
		<MODE>0</MODE>
		<INSERT>BLOG_EDIT_BLOG</INSERT>
		<PERMISSION>75</PERMISSION>
		<ONSUCCESS>
			<GOTO>blog_read_edit_blog</GOTO>
		</ONSUCCESS>
		<ONERROR>
			<GOTO>blog_read_edit_blog</GOTO>
		</ONERROR>
	</BLOG_READ_EDIT_BLOG>
	<BLOG_WRITE_EDIT_BLOG>
		<TYPE>write</TYPE>
		<MODE>0</MODE>
		<TEMPLATE>MESSAGE</TEMPLATE>
		<PERMISSION>75</PERMISSION>
		<ONSUCCESS>
			<GOTO>blog_read_edit_blog</GOTO>
		</ONSUCCESS>
		<ONERROR>
			<GOTO>blog_read_edit_blog</GOTO>
		</ONERROR>
	</BLOG_WRITE_EDIT_BLOG>
	<BLOG_WRITE_DELETE_BLOG>
		<TYPE>write</TYPE>
		<MODE>0</MODE>
		<TEMPLATE>MESSAGE</TEMPLATE>
		<PERMISSION>75</PERMISSION>
		<ONSUCCESS>
			<GOTO>blog_read_edit_blog</GOTO>
		</ONSUCCESS>
		<ONERROR>
			<GOTO>blog_read_edit_blog</GOTO>
		</ONERROR>
	</BLOG_WRITE_DELETE_BLOG>
	<BLOG_DEFAULT_NEW_BLOG>
		<TYPE>default</TYPE>
		<MODE>0</MODE>
		<INSERT>BLOG_NEW_BLOG</INSERT>
		<PERMISSION>30</PERMISSION>
		<ONSUCCESS>
			<GOTO>blog_default_new_blog</GOTO>
		</ONSUCCESS>
		<ONERROR>
			<GOTO>blog_default_new_blog</GOTO>
		</ONERROR>
	</BLOG_DEFAULT_NEW_BLOG>
	<BLOG_WRITE_NEW_BLOG>
		<TYPE>write</TYPE>
		<MODE>0</MODE>
		<TEMPLATE>MESSAGE</TEMPLATE>
		<PERMISSION>30</PERMISSION>
		<ONSUCCESS>
			<GOTO>blog_read_read_blog</GOTO>
		</ONSUCCESS>
		<ONERROR>
			<GOTO>blog_default_new_blog</GOTO>
		</ONERROR>
	</BLOG_WRITE_NEW_BLOG>
	<BLOG_READ_SEARCH_BLOG>
		<TYPE>read</TYPE>
		<MODE>0</MODE>
		<INSERT>BLOG_SEARCH_BLOG</INSERT>
		<PERMISSION>0</PERMISSION>
		<ONSUCCESS>
			<GOTO>blog_read_search_blog</GOTO>
		</ONSUCCESS>
		<ONERROR>
			<GOTO>blog_read_search_blog</GOTO>
		</ONERROR>
	</BLOG_READ_SEARCH_BLOG>
	<BLOG_READ_READ_BLOG>
		<TYPE>read</TYPE>
		<MODE>0</MODE>
		<INSERT>BLOG_READ_BLOG</INSERT>
		<PERMISSION>0</PERMISSION>
		<ONSUCCESS>
			<GOTO>blog_read_read_blog</GOTO>
		</ONSUCCESS>
		<ONERROR>
			<GOTO>blog_read_read_blog</GOTO>
		</ONERROR>
	</BLOG_READ_READ_BLOG>
</INTERFACE>

Vergleichen Sie den obigen Quellcode mit Ihrem Ergebnis.

Literaturhinweise
Falls Sie sich tiefer mit den in diesem Abschnitt behandelten Themen beschäftigen wollen, finden Sie Anleitung in folgenden Artikeln:

Kapitel 5: Editieren des PHP-Quellcodes

Der folgende Abschnitt soll Ihnen zeigen, wie Sie den PHP-Quellcode eines Plugins editieren können, um neue Funktionen hinzuzufügen oder existierende Funktionen Ihren Bedürfnissen anzupassen.

In diesem Abschnitt des Tutorials soll ein automatisch generierter RSS-Feed für die 10 neuesten Einträge des Blog implementiert werden. Das Tutorial führt Sie durch die verschiedenen Schritte der Erstellung.

Definieren einer neuen Aktion im Interface-Abschnitt der Konfigurationsdatei

Bevor Sie den PHP-Quellcode editieren, sollten Sie die neue Aktion in der Schnittstelle des Plugins eintragen. Nur dann kann diese auch über den Webbrowser aufgerufen werden. Dies ist dient einerseits der Performance und ist andererseits eine zusätzliche Sicherheitsmaßnahme, um das absichtliche Einschleusen fremden PHP-Codes in die Anwendung zu erschweren, das versehentliche Ausführen von Code zu verhindern und insgesamt Plugins damit sicherer zu machen.

Um diesen Schritt durchzuführen, öffnen Sie die Datei "plugins/blog.config" in PSPad (beachten Sie, dass sie den Namen "blog" durch den Namen Ihres Plugins ersetzen müssen). Wählen Sie den Highlighter "Yana Framework" aus.

Fügen Sie im Container "INTERFACE" eine neue Aktion ein (Shortcut "act"). Nennen Sie diese Aktion "blog_rss".

Ihr Quellcode sollte nun die folgende neue Aktion enthalten:

<INTERFACE>
[...]
	<BLOG_RSS>
		<TYPE>default</TYPE>
		<MODE>0</MODE>
		<PERMISSION>0</PERMISSION>
		<TEMPLATE>INDEX</TEMPLATE>
		<INSERT></INSERT>
		<ONSUCCESS>
			<TEXT>200</TEXT>
			<GOTO></GOTO>
		</ONSUCCESS>
		<ONERROR>
			<TEMPLATE>ALERT</TEMPLATE>
			<TEXT>500</TEXT>
			<GOTO></GOTO>
		</ONERROR>
	</BLOG_RSS>
[...]
</INTERFACE>

Nicht alle der automatisch eingefügten Felder werden benötigt. Passen Sie die Definition der Aktion nun wie folgt an:

<INTERFACE>
[...]
	<BLOG_RSS>
		<TYPE>read</TYPE>
		<MODE>0</MODE>
		<TEMPLATE>NULL</TEMPLATE>
		<PERMISSION>0</PERMISSION>
	</BLOG_RSS>
[...]
</INTERFACE>

Das Feld "TYPE" mit dem Wert "read" hat etwas mit dem Verhalten dieser Aktion zu tun. Dieser Typ drückt aus, dass diese Aktion lediglich lesend auf die Datenbank zugreifen muss. Diese Information kann für eine bessere Performance ausgenutzt werden.

Das Feld "MODE" mit dem Wert "0" sagt aus, dass der normale Betriebsmodus verwendet wird. (Mit dem Wert "1" startet das Programm für diese Aktion im "abgesicherten Modus").

Das Feld "PERMISSION" mit dem Wert "0" sagt aus, dass jeder Besucher auf diese Aktion zugreifen darf, ohne besondere Anforderungen an seinen Sicherheitslevel.

Das Feld "TEMPLATE" gibt an, welches Template für die Aktion ausgewählt werden soll. Zwar ist es möglich das Template auch aus dem PHP-Code heraus auszuwählen, allerdings ist die Verwendung dieses Feldes in der Konfigurationsdatei übersichtlicher und einfacher.
Das hier ausgewählte Template "NULL" ist ein vordefinierter Spezialwert. Er drückt aus, dass "kein Template" ausgewählt werden soll. Dies ist in diesem Fall auch nicht erforderlich, weil die Ausgabe durch einen automatischen RSS-Generator, ohne Template, erzeugt werden wird.

Damit sind die Vorbereitungen abgeschlossen der folgende Abschnitt wird sich mit der Implementierung im PHP-Quellcode beschäftigen.

Schreiben des PHP-Quellcodes

Öffnen Sie die Datei "plugins/blog/plugin.php" in PSPad (beachten Sie, dass sie den Namen "blog" durch den Namen Ihres Plugins ersetzen müssen). Wählen Sie den Highlighter "PHP" aus.

Fügen Sie in die Klasse "plugin_blog" eine neue Funktion mit dem Namen "blog_rss" ein. Um sich Schreibarbeit zu ersparen, können Sie folgende Vorlage verwenden.

<?php
class plugin_blog extends plugin
{
// [...]
    /**
     * blog_rss
     *
     * returns bool(true) on success and bool(false) on error
     *
     * Type:        read
     * Permission:  0
     * Templates:   NULL
     *
     * @access  public
     * @return  bool
     * @name    plugin_blog::blog_rss()
     * @param   array  $ARGS  array of params passed to the function
     */
    function blog_rss ($ARGS)
    {

    }
// [...]
}
?>

Meine persönliche Empfehlung ist, Quellcode, denn Sie geschrieben haben, stets sofort zu dokumentieren, solange Ihnen der Aufbau und die Funktionsweise noch frisch im Gedächtnis sind. Dies hat zudem den unschätzbaren Vorteil, dass Sie sich dadurch zwangsweise noch einmal mit dem gerade beschriebenen Code beschäftigen müssen.

Abfrage der Datenbank

Um einen RSS-Feed der 10 aktuellsten Beiträge zu erstellen, müssen Sie zunächst erst einmal die 10 aktuellsten Beiträge aus der Datenbank laden. Dazu erstellen Sie ein Datenbankabfrage der Tabelle "blog". Durch Setzen der Limit-Klausel auf "10" limitieren Sie die Anzahl der Einträge des Resultsets auf maximal 10 Stück. Damit Sie tatsächlich die 10 neuesten Einträge erhalten, sortieren Sie die Einträge absteigend nach dem Datum Ihrer Erstellung. Das heißt nach der Spalte "blog_created". Verwenden Sie dazu "order_by" und "desc".

Der folgende Quellcode demonstriert diese Abfrage.

<?php
/* get entries from database */
$query = array(
    'key' => 'blog.*',
    'order_by' => 'blog_created',
    'desc' => true,
    'limit' => 10
);
$rows = $this->database->get($query);
?>

Wie Sie in diesem Beispiel sehen, verfügt das Yana Framework über einen Query-Generator zum Erzeugen einfacher SQL-Statements. Sie benötigen also keinerlei SQL-Kenntnisse, um mit dem Yana Framework Abfragen auf einer Datenbank durchführen zu können. Das Mapping der tatsächlichen SQL-Statements auf die passende Syntax des eigentlichen DBMS erledigt das Framework ebenfalls automatisch.

Der Query-Generator ist außerdem in der Lage, automatisiert einfache Sicherheitsprüfungen durchzuführen, automatisches Quoting für Eingabewerte zu realisieren und SQL-Abfragen auf Plausibilität zu prüfen, ohne diese an die Datenbank zu senden. Dies reduziert zusätzlich das Risiko von SQL-Injections und erhöht dadurch die Sicherheit Ihrer Anwendung.

Das Resultset, hier $rows, besteht aus einem mehrdimensionalen, assoziativen Array. Jeder Eintrag entspricht einer Zeile. Jede Zeile wiederum hat jeweils einen Eintrag pro Spalte.

Ein Aufruf von var_export($rows) demonstriert dies. Die Ausgabe lautet wie folgt:

<?php
array (
  2 =>
  array (
    'BLOG_TITLE' => 'Testeintrag',
    'BLOG_TEXT' => 'Das ist ein Test[br]Das ist ein Test[br]Das ist ein Test[br]Das ist ein Test',
    'BLOG_AUTHOR' => 'Thomas Meyer',
    'BLOG_CREATED' => '1173276511',
    'PROFILE_ID' => 'default',
    'BLOG_ID' => 2,
  ),
  1 =>
  array (
    'BLOG_TITLE' => 'Testeintrag',
    'BLOG_TEXT' => 'Das ist ein Test.[br]Nur ein Test.[br][br]Neue Zeile.',
    'BLOG_AUTHOR' => 'Thomas Meyer',
    'BLOG_CREATED' => '1173276442',
    'PROFILE_ID' => 'default',
    'BLOG_ID' => 1,
  ),
)
?>

Wie Sie am Index des Arrays sehen, sind die Einträge in umgekehrter Reihenfolge, also absteigend, sortiert. Die Spaltennamen werden in Großbuchstaben ausgegeben.

Weitere Details und Codebeispiele finden Sie im Kochbuch für Entwickler, Kapitel Datenbanken und in der API-Dokumentation der Klasse "DbStream".

Zur Repräsentation von RSS-Feeds dient die Klasse "RSS". Um einen neuen Feed zu erzeugen, sollte als nächster Schritt eine Instanz dieser Klasse erzeugt werden.

<?php
$rss = new RSS();
$rss->title = 'Blog';
$rss->description = 'the 10 most recent blog entries';
?>

Den Titel und die Beschreibung des RSS-Feed können Sie frei wählen. Verwenden Sie dazu die Eigenschaften "title" und "description", wie im Beispiel gezeigt.

Anschließend ist für jeden Eintrag der Datenbank ein Eintrag im RSS-Feed zu erstellen. Ein Eintrag wird repräsentiert durch die Klasse "RSSitem". Um einen Eintrag zu erzeugen, wird eine neue Instanz dieser Klasse erzeugt und diese mithilfe der Methode RSS::addItem() dem RSS-Feed hinzugefügt. Die Einträge werden im RSS-Feed in der Reihenfolge abgelegt, in welcher Sie eingefügt werden - unabhängig vom Datum, da das Datum lediglich ein optionales Feld ist.

Der folgende Quellcode demonstriert das Erzeugen der Einträge.

<?php
foreach ($rows as $row)
{
    $item = new RSSitem();
    // Titel
    $item->title = $row['BLOG_TITLE'];
    // Link
    $action = 'blog_read_read_blog';
    $blog_id = $row['BLOG_ID'];
    $link = DisplayUtility::url("action=$action&blog_id=$blog_id", true);
    $link = str_replace(session_name() . '=' . session_id(), '', $link);
    $item->link = $link;
    // Text
    $item->description = $row['BLOG_TEXT'];
    // Datum
    $item->pubDate = date('r', $row['BLOG_CREATED']);
    // Eintrag hinzufügen
    $rss->addItem($item);
} /* end foreach */
?>

Beachten Sie den Code zum Erzeugen des Links. Dieser verweist auf die Aktion, welche zur Darstellung von Einträgen des Blogs verwendet wird. Die Aktion lautet "blog_read_read_blog". Wie bereits erwähnt, wurde dieser Name automatisch generiert. Die Funktion "url()" der Utility-Klasse "DisplayUtility" erzeugt, wie der Name sagt, eine URL inklusive der Adresse des Servers, Name und Pfad des Skripts und aller erforderlicher Parameter.

Der daraus entstehende Link enthält allerdings auch die aktuelle Session-Id. Diese ändert sich naturgemäß bei jedem Aufruf. Eigentlich sollte dies kein Problem darstellen, allerdings gibt es bedauerlicherweise eine Schwäche moderner RSS-Reader. Denn einige (nicht alle) von diesen sind so programmiert, dass Sie den Link eines RSS-Eintrags gleichzeitig als eindeutige Id verwenden. Sogar wenn explizit eine GUID vorhanden ist, wird diese in der Regel ignoriert und trotzdem der Link benutzt. Aus diesem Grund darf er sich nicht verändern, weil diese Programme andernfalls durcheinander geraten. Das ist der Grund, warum die Session-Id unbedingt aus dem Link entfernt werden muss und das ist auch der Grund, warum der Primärschlüssel des Eintrags im Link auftauchen muss. Dies ist keine Einschränkung des Frameworks, sondern eine unangenehme Eigenschaft der RSS-Reader. Leider werden Sie, wohl oder übel, vorerst mit diesem Problem leben müssen.

Weitere Details zur Verwendung dieser Klasse finden Sie in der API-Dokumentation der Klassen "RSS" und "RSSitem".

Zum Vergleich zeigt der folgende Auszug den gesamten Quellcode der Aktion im Zusammenhang:

<?php
/* get entries from database */
$query = array(
    'key' => 'blog.*',
    'order_by' => 'blog_created',
    'desc' => true,
    'limit' => 10
);
$rows = $this->database->get($query);
$rss = new RSS();
$rss->title = 'Blog';
$rss->description = 'the 10 most recent blog entries';
foreach ($rows as $row)
{
    $item = new RSSitem();
    // Titel
    $item->title = $row['BLOG_TITLE'];
    // Link
    $action = 'blog_read_read_blog';
    $blog_id = $row['BLOG_ID'];
    $link = DisplayUtility::url("action=$action&blog_id=$blog_id", true);
    $link = str_replace(session_name() . '=' . session_id(), '', $link);
    $item->link = $link;
    // Text
    $item->description = $row['BLOG_TEXT'];
    // Datum
    $item->pubDate = date('r', $row['BLOG_CREATED']);
    // Eintrag hinzufügen
    $rss->addItem($item);
} /* end foreach */
print utf8_encode($rss->toString());
exit(0);
?>

Wie Sie aus dem obigen Quellcode sehen konnten, wird in jedem Eintrag auf die Aktion "blog_read_read_blog" mit dem Parameter "blog_id" verwiesen. Bis jetzt besitzt diese Aktion allerdings diesen Parameter noch nicht. Der folgende Abschnitt wird demonstrieren, wie dieser Parameter dieser Aktion hinzugefügt wird.

Hinzufügen eines neuen Parameters

Suchen Sie in dem Dokument die Aktion "blog_read_read_blog". Diese sollte momentan den folgenden Quellcode aufweisen:

<?php
/**
 * blog_read_read_blog
 *
 * returns bool(true) on success and bool(false) on error
 *
 * Type:        read
 * Permission:  0
 * Templates:   BLOG_READ_BLOG
 *
 * @access  public
 * @return  bool
 * @name    plugin_blog::blog_read_read_blog()
 * @param   array  $ARGS  array of params passed to the function
 */
function blog_read_read_blog ($ARGS)
{
    /* check input data */
    assert('is_array($ARGS);');
    settype($ARGS, 'array');

    /* global variables */
    global $YANA;

    /* do something */
    return true;
}
?>

Zunächst sollten Sie prüfen, ob der Parameter "blog_id" überhaupt gesetzt ist, da dies nicht immer der Fall sein muss. Weil die Spalte "blog_id" in der Tabelle "blog" vom Typ "integer" ist, sollten Sie außerdem prüfen, ob der Eingabewert numerisch ist. Außerdem sollten Sie den Typ des Eingabewertes in einen Integerwert ändern. Der folgende Quellcode demonstriert dies.

<?php
if (isset($ARGS['blog_id']) && is_numeric($ARGS['blog_id'])) {
    $id = (int) $ARGS['blog_id'];
}
?>

An dieser Stelle kommt nun zum Tragen, dass Sie zuvor ( siehe oben ) im Template dieser Aktion für die Funktion "create" den Wert des Parameters "where" auf die Variable "$WHERE" gesetzt haben, denn dadurch können Sie nun durch Setzen der Variable "$WHERE" diesen Parameter beeinflussen.

Um den Wert einer Variable zu setzen rufen Sie die Funktion Yana::setVar auf. Setzen Sie den Wert der Variable auf "blog_id=$id".

<?php
if (isset($ARGS['blog_id']) && is_numeric($ARGS['blog_id'])) {
    $id = (int) $ARGS['blog_id'];
    $YANA->setVar('WHERE', "blog_id=$id");
}
?>

Abschließend soll noch ein weiteres Feature demonstriert werden. Das Framework kann, falls ein RSS-Feed vorhanden ist, automatisch eine Grafik mit der Aufschrift "RSS" und einen Link auf den RSS-Feed der Anwendung einblenden. Um dieses Feature zu aktivieren, muss lediglich eine Variable gesetzt werden. Der Name dieser Variable lautet "RSS_ACTION" und ihr Wert sollte der Name der Aktion sein, welche den RSS-Feed erzeugt. In diesem Fall "blog_rss".

Die folgende Abbildung zeigt, wie dieses Symbol im Browser dargestellt wird.

Screenshot
Abbildung: Darstellung des Plugins mit RSS-Symbol (Firefox 2.0)

Zum Vergleich noch einmal der gesamte Quellcode der Aktion im Zusammenhang.

<?php
/**
 * blog_read_read_blog
 *
 * returns bool(true) on success and bool(false) on error
 *
 * Type:        read
 * Permission:  0
 * Templates:   BLOG_READ_BLOG
 *
 * @access  public
 * @return  bool
 * @name    plugin_blog::blog_read_read_blog()
 * @param   array  $ARGS  array of params passed to the function
 */
function blog_read_read_blog ($ARGS)
{
    /* check input data */
    assert('is_array($ARGS);');
    settype($ARGS, 'array');

    /* global variables */
    global $YANA;
    $YANA->setVar('RSS_ACTION', 'blog_rss');
    if (isset($ARGS['blog_id']) && is_numeric($ARGS['blog_id'])) {
        $id = (int) $ARGS['blog_id'];
        $YANA->setVar('WHERE', 'blog_id=' . $id);
    }
    return true;
}
?>

Vergleichen Sie Ihr Ergebnis mit dem obigen Quellcode.

Mit diesem Schritt ist die Erstellung Ihres ersten Plugins erfolgreich abgeschlossen.

Literaturhinweise
Falls Sie sich tiefer mit den in diesem Abschnitt behandelten Themen beschäftigen wollen, finden Sie Anleitung in folgenden Artikeln:

Kapitel 6: Zusammenfassung

In diesem Tutorial haben Sie gelernt, wie Sie:

Damit ist dieses Tutorial beendet. Weitere Informationen und Codebeispiele finden Sie unter anderem im Kochbuch für Entwickler und der API-Dokumentation des Yana Frameworks.

Quellcodes

Alle in diesem Tutorial verwendeten Quellcodes finden Sie auch in folgendem Paket: Blog-Plugin

PHP-Programme auf CD-ROM brennen

Das folgende Tutorial wird erläutern, wie Sie Ihre Webanwendung mit dem Yana PHP-Framework und Server2Go auf eine CD/DVD-ROM brennen und direkt von dort starten können.

Der Zeitaufwand um alle Schritte nachzuvollziehen beläuft sich auf etwa 1/2 Stunde, nicht gerechnet die Zeit für eventuell notwendige Downloads. Literaturhinweise zu thematisch verwandten Artikeln finden Sie jeweils am Ende eines Abschnitts.

Systemvoraussetzungen

Kapitel 1: Quellen downloaden

Bevor Sie mit diesem Tutorial beginnen, sollten Sie sicherstellen, dass Sie einige Vorbereitungen abgeschlossen haben, da Sie andernfalls an eine Stelle gelangen könnten, an der Sie das Tutorial nicht fortsetzen können.

Server2Go ist Donationware und darf auch für kommerzielle Anwendungen kostenlos verwendet werden. Die Software wird von Timo Haberkern entwickelt und betreut.

Grundlegende Kenntnisse im Aufbau und der Funktion von PHP und MySQL-Datenbanken werden in diesem Artikel vorausgesetzt.

Hier einige vorbereitete Konfigurationsdateien für Server2Go. Diese Dateien basieren auf Version 1.5.0. Die Angaben gelten ohne Gewähr. Hier finden Sie Links zu einigen weiteren nützlichen Quellen:

Kapitel 2: CD-ROM vorbereiten

Um ein PHP-Programm mit dem Yana PHP-Framework direkt von CD starten zu können gehen Sie bitte wie folgt vor.

  1. Grundinstallation
    1. Entpacken Sie Server2Go.
    2. Kopieren Sie das Yana PHP-Framework in das Verzeichnis "htdocs/" des Webservers.
    3. Editieren Sie die Datei "server/config_tpl/php.ini" in einem Texteditor Ihrer Wahl. Ändern Sie den Wert "memory_limit" von "8M" auf mindestens "16M". Empfohlen sind "128M", der tatsächliche Wert ist jedoch abhängig von Ihrer PHP-Anwendung. Da bei einer CD-Anwendung nicht mehrere Nutzer gleichzeitig auf das Programm zugreifen sondern stets nur eine Person allein, brauchen Sie sich nicht zu scheuen, hier einen hohen Wert einzutragen.
    4. Öffnen Sie die Konfigurationsdatei "htdocs/yana/library.php" in einem Texteditor (z.Bsp. ConTEXT, oder PSPad).

    Die Datei "library.php" ändern Sie wie folgt: define('YANA_CDROM', true);

  2. Datenbankkonfiguration

    Falls Ihr Programm eine MySQL-Datenbank benötigt, gehen Sie wie folgt vor:

    1. Editieren Sie die Datei "pms_config.ini" im Server2Go-Verzeichnis und aktivieren Sie MySQL, indem Sie "UseMySQL" auf "1" setzen.
    2. Starten Sie Server2Go durch Ausführen der Datei "Server2Go.exe".
    3. Es wird automatisch Ihr Browser geöffnet. Auf der Startseite finden Sie im rechten Seitenmenü einen Link zu PHPMyAdmin. Die Adresse lautet: http://127.0.0.1:4001/phpmyadmin/ Klicken Sie diesen Link an, oder rufen Sie die Adresse direkt über die Adressleiste Ihres Browsers auf.
    4. Installieren Sie mit PHPMyAdmin Ihre Datenbanken. Achten Sie darauf, dass Sie den gleichen Namen für Ihre Datenbank verwenden, den Sie für Ihre lokale Installation verwendet haben. Andernfalls müssen Sie die Datenbankverbindungseinstellungen des Yana PHP-Framework entsprechend anpassen.
    5. Falls Sie die Datenbankverbindung für das Framework ändern müssen, finden Sie die Verbindungseinstellungen in der Datei "htdocs/yana/config/".
    6. Installieren Sie PEAR-DB. Gehen Sie dazu auf die Download Site und kopieren Sie das Archiv für DB und das PEAR Package auf Ihren Rechner. Sie werden ein Programm benötigen, dass die beiden TGZ-Archive entpacken kann. Sollten Sie keines besitzen, finden Sie zum Beispiel auf 7-Zip ein kostenloses Open-Source Programm, mit welchem Sie die Archive öffnen können.
    7. Die Archive sind 2 mal verpackt - Sie müssen also nachdem Sie die erste Datei entpackt haben die zweite Datei ebenfalls entpacken. Darin enthalten sind XML-Dateien, welche Sie ignorieren können, und jeweils ein Verzeichnis mit Installationsdateien. Kopieren Sie den Inhalt beider Installationsverzeichnisse in das Verzeichnis "server/php/pear/", so dass die Dateien "DB.php" und "PEAR.php" beide direkt in diesem Verzeichnis liegen. Damit ist die Installation für PEAR-DB abgeschlossen. Sie können dies testen indem Sie Server2Go starten und das Yana PHP-Framework mit dem Parameter "yana/index.php?action=test" aufrufen. Auf der Seite sollte in grüner Schrift bestätigt sein, dass PEAR-DB erfolgreich gefunden wurde.
  3. Server2Go - Konfiguration

    Nach der Installation Ihrer Datenbanken fahren Sie mit der Konfiguration fort.

    1. Um Ihnen die Aufgabe zu erleichtern, wurden für dieses Handbuch alle Einstellungen vorkonfiguriert, welche Sie für Ihre CD-ROM benötigen. Sie müssen die Dateien lediglich in das Server2Go-Installationsverzeichnis entpacken. Überschreiben Sie dabei die alten Konfigurationsdateien. Das ZIP-Archiv finden Sie hier.
    2. Konfigurieren Sie anschließend die Datenbankeinstellungen in der Datei "pms_config.ini" und den Autostart-Eintrag gemäß Ihren Wünschen. Eventuell möchten Sie auch Ihr eigenes Logo einbinden.

Anschließend kann das Paket direkt auf CD-ROM gebrannt und sofort verwendet werden.

Im nächsten Kapitel werden Sie erfahren, wie Sie Server2Go und das Yana PHP-Framework zusammen mit der Portable-Edition des Firefox Browser verwenden können.

Kapitel 3: Verwendung mit Firefox-Portable

Sie haben die Möglichkeit mit Server2Go auch einen Firefox-Browser direkt von CD zu starten. Die folgende Anleitung erklärt Ihnen, was dazu nötig ist.

Achtung: Firefox-Portable kann (soweit bekannt) mit Version 1.5.1 von Server2Go zur Zeit NICHT auf CD-ROM, sondern nur auf USB-Stick oder Festplatte verwendet werden. Das Problem wird in einer kommenden Version beseitigt sein. In der Zwischenzeit ist es möglich einen alternativen Browser zu verwenden. Eine von mehreren Möglichkeiten ist das Zusatzprogramm "SimpleBrowser" von der Server2Go Website zu verwenden. Der Autor erwartet im Gegenzug eine geringe Spende für die Weiterentwicklung der Software.
  1. Firefox Portable installieren
    1. Zuerst benötigen Sie eine aktuelle, portable Version des Browsers. Diese finden Sie auf der Website http://portableapps.com. Laden Sie diese Datei aus dem Netz und entpacken Sie sie in das Server2Go-Installationsverzeichnis (dort, wo sich "Server2Go.exe" befindet).
    2. Der Browser wird auf dieser Seite in Englisch angeboten. Sie können diesen jedoch in eine deutsche Version umwandeln. Laden Sie dazu das deutsche Sprachpaket herunter. Sie finden dieses unter anderem auf www.firefox-browser.de. Kopieren Sie die Datei "de.xpi" auf Ihren Rechner.
    3. Starten Sie FirefoxPortable, indem Sie die Datei "FirefoxPortable/FirefoxPortable.exe" ausführen. Installieren Sie die Datei "de.xpi", indem Sie sie mit entweder mit der Maus auf das Firefox-Fenster ziehen, oder indem Sie das Menü "Datei / Datei öffnen ..." anklicken und die Datei "de.xpi" aus dem Explorer-Fenster wählen.
    4. Starten Sie den Browser anschließend 1 Mal neu.
  2. Server2Go für Firefox Portable konfigurieren

    Achtung: Es gibt ein ZIP-Archiv mit allen erforderlichen Konfigurationsdateien, welches Sie verwenden können. Entpacken Sie das Archiv und überschreiben Sie alle Originaldateien. Danach sind Sie bereits fertig und können Ihre Anwendung direkt auf CD-ROM brennen.

    Falls Sie das Archiv nicht verwenden und die Schritte stattdessen von Hand durchführen wollen, fahren Sie mit der Konfiguration wie folgt fort.

    1. Öffnen Sie die Datei "pms_config.ini".
    2. Ändern Sie den Wert "BrowserType" auf "EXTERNAL"
    3. Ändern Sie den Wert "BrowserPath" auf "FirefoxPortable/FirefoxPortable.exe"
    4. Speichern Sie die Datei.
    5. Erzeugen Sie eine neue Datei: "FirefoxPortable/FirefoxPortable.ini" mit folgendem Inhalt:
      [FirefoxPortable]
      FirefoxDirectory=App\firefox
      ProfileDirectory=Data\profile
      PluginsDirectory=Data\plugins
      SettingsDirectory=Data\settings
      FirefoxExecutable=firefox.exe
      AdditionalParameters=-contentLocale de-DE -UILocale de-DE
      LocalHomepage=
      DisableSplashScreen=true
      DisableIntelligentStart=false
      AllowMultipleInstances=true
      SkipChromeFix=false
      SkipCompregFix=false
      WaitForFirefox=true
      RunLocally=true
      Eine Anleitung zu den verwendeten Optionen finden Sie in der Datei "FirefoxPortable/Other/FirefoxPortableSource/Readme.txt". Diese Datei wird mit Firefox Portable ausgeliefert. Die Option "AdditionalParameters" sorgt hier für das Starten der deutschen Version.

Anschließend kann das Paket auf CD-ROM gebrannt werden.

Warnung: es besteht die Möglichkeit, dass Server2Go auf einigen Rechnern aufgrund lokaler Firewalls oder eingeschränkter Nutzerrechte nicht korrekt funktioniert. Es ist daher dringend empfohlen, dass Sie Ihre CD-ROM auf mindestens einem anderen Testsystem ausprobieren. Unter einigen Betriebssystemen können Administratorrechte notwendig sein um die CD zu starten.
Windows Vista: Unterstützung für MS Vista wurde für Server2Go ab Version 1.5.0 eingeführt. Es kann passieren, dass der Nutzer gefragt wird, ob die Anwendung auf das System zugreifen darf. Bis Version 1.5.0 sind unter Vista Administratorrechte erforderlich um Server2Go von einer CD-ROM zu starten.
Windows 98: Für Rechner mit Windows 98, welche KEIN Microsoft Office Paket installiert haben, muss ein Patch von Microsoft installiert werden. Sie finden diesen Patch unter folgender URL: http://www.microsoft.com/downloads/details.aspx?FamilyID=6c050fe3-c795-4b7d-b037-185d0506396c&DisplayLang=de
Um einen stabilen Betrieb sicherzustellen ist außerdem ein Downgrade der MySQL-Datenbank auf Version 4 erforderlich. Dazu genügt es, die Dateien der Datenbankanwendung im Verzeichnis "server/mysql/" auszutauschen. Ein passendes Installationspaket kann von der Server2Go Website bezogen werden.

Artikel

XML Data Definition Language Format

Abstrakt

Dieses Dokument definiert das XDDL Dateiformat. Dieses Format dient der herstellerunabhängigen Darstellung der Struktur von Datenbanken und deren Repräsentation im Kontext einer Anwendung. Begleitend zu diesem Dokument existieren DTDs, welche die Struktur einer gültigen XDDL-Datei beschreiben. Das Dokument beinhaltet eine syntaktische und semantische Beschreibung der Elemente. Ergänzend werden informelle Empfehlungen zur Darstellung der Elemente durch einen Client gegeben.

Status dieses Dokumentes

Dieser Abschnitt beschreibt den Status des Dokumentes zum Zeitpunkt der Veröffentlichung. Spätere Dokumente können den vorliegenden Stand ersetzen. Die jeweils aktuelle Version finden Sie online auf der Projekt-Webseite des Yana Frameworks.

Dieses Dokument ist noch keine endgültige Fassung (Final Release) und seine Inhalte können sich ändern. Kommentierungen der gegenwärtigen Version dieser Arbeit sind erwünscht.

Die aktuelle Version dieses Dokumentes wird innerhalb des Subversion-Repository gepflegt. Eine Liste von Änderungen kann aus dem Repository jederzeit exportiert werden.

Working Draft
Ein Zustand, in welchem alle Elemente kontinuierlichen Änderungen unterworfen sein können.
Call for Comments
Das Dokument ist gesperrt und jegliche Änderungen (abgesehen von Korrekturen an Rechtschreibung und Grammatik) sind untersagt. Kommentare zum gegenwärtigen Stand des Dokumentes werden aufgenommen. Der nachfolgende Zustand ist wahrscheinlich "Working Draft" (um Änderungsvorschläge einzuarbeiten), oder "Final Call", falls es keine Anmerkungen gab.
Final Call
Das Dokument ist gesperrt und jegliche Änderungen (abgesehen von Korrekturen an Rechtschreibung und Grammatik) sind untersagt. Falls keine Anmerkungen aufgenommen werden, wird das folgende Dokument ohne Änderungen veröffentlicht.
Released Candidate Recommendation / Unstable
Das Dokument ist eine veröffentlichte Version, aber Anmerkungen zum gegenwärtigen Zustand des Dokumentes werden weiter aufgenommen, als Vorbereitung für spätere Versionen.
Released Recommendation / Stable
Das Dokument ist eine veröffentlichte, stabile Version. Es wird noch aktiv gepflegt.
Superseded
Das Dokument ist durch eine spätere, stabilere Version ersetzt worden. Es wird nicht mehr aktiv gepflegt.
VersionStateDate
nicht versioniertWorking Draft2009-07-01 - 2009-08-31
0.5Call for Comments2009-09-17 - 2009-10-05
0.5.1Working Draft2009-10-06 - 2010-09-13
0.6Working Draft2010-09-14 - heute
0.7Call for Commentsnachfolgend
Autoren
Thomas Meyer
Änderungsdatum
$Date: 2010-09-14 16:06:25 +0200 (Mo, 14 Aug 2010) $

Definitionen

Terminologie

Dieser Abschnitt definiert in diesem Dokument verwendete, feststehende Bezeichnungen.

Darf
Eine optionale Definition. Programmierer können entscheiden, ob Sie diese befolgen wollen oder auch nicht.
Muss
Eine verpflichtende Anforderung. Implementierungen müssen diese Bedingungen erfüllen.
Optional
siehe "Darf"
Soll
siehe "Muss"
Sollte
Eine Empfehlung. Programmierer werden ermutigt, diese Regel zu befolgen, aber sie können sich dennoch entscheiden sie zu ignorieren.
Unterstützt
Ein unterstütztes Feature muss von der Implementierung bereitgestellt werden und sich wie festgelegt verhalten.
Undefiniert / nicht spezifiziert
Keine Anforderungen sind spezifiziert. Der Entwickler kann entscheiden ob und wie auf diese Situation reagiert werden soll. Jedoch darf die Implementierung für eine undefinierte Situation kein spezifisches Verhalten voraussetzen.

Glossar

DTD
Eine Definition der gültigen Struktur, der Elemente, und Attribute für ein valides XML Dokument, welches die Regeln der DTD erfüllt.
Element
Ein Teil der in der DTD definierten Dokumentstruktur. Jedes Element kann mehrere Attribute besitzen.
Attribute
Ein Teil der in der DTD definierten Dokumentstruktur. Im Wesentlichen ein Schlüssel-Wert-Paar.
Dokument
Bezieht sich auf eine gültige XML-Datei, welche die durch die DTD definierten Regeln erfüllt. Jedes Dokument kann mehrere Elemente enthalten.
PCData
Ein Teil der in der DTD definierten Dokumentstruktur. Besagt, dass ein Element Textinhalt haben kann.
Empty
Ein Teil der in der DTD definierten Dokumentstruktur. Besagt, dass ein Element keinen Inhalt haben darf.

Sonstiges

Eine Referenzimplementierung dieses Formats ist durch das Yana Framework gegeben. Diese ist eine Empfehlung und nicht Teil der XDDL-Definition. Das Dokument erläutert optionale Elemente anhand dieser Referenzimplementierung. Dieser Erläuterungen haben informellen Charakter. Hinweise zur Darstellung im Client, Abbildungen von Möglichkeiten der Darstellung und Beispiele für HTML-Code sind stets Empfehlungen und sind rein informell.

Datenbank

Database ist der Wurzelknoten eines XDDL Dokuments. Er kann mehrere Kindelemente enthalten. Diese können aufgeteilt werden auf 5 grundlegende Gruppen : Tabellen, Views, Formulare, Funktionen und Change-logs. Das Element Database definiert grundlegende Eigenschaften der Datenbank selbst, sowie Information für den Client und Anwendungen, die sich mit der Datenbank verbinden wollen.

Element Database

  ELEMENT database (description?, (include | table | view | form | function |
                     sequence | initialization)*, changelog?)
  ATTRIBUTE
       name        string
       title       string
       charset     string
       datasource  string
       readonly    bool
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string - - Ein eindeutiger Name welcher diese Datenbank identifiziert. Default ist der Dateiname. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
title string - - Title ist eine Beschriftung, welche in der Nutzeroberfläche angezeigt werden sollte wenn das Objekt anzeigt wird.
Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
charset string - - Der bevorzugte Zeichensatz welcher verwendet wird wenn Datenbankobjekte erstellt werden und/oder mit der Datenbank kommuniziert wird. Der Zeichensatz kann nur zum Zeitpunkt der Erstellung der Datenbank gesetzt werden. Wenn Sie sich dafür entscheiden, eine vorhandene Datenbank zu verwenden, beachten Sie bitte, dass der tatsächlich verwendete Zeichensatz ein anderer sein könnte.
datasource string - - Die Interpretation des Attributs datasource (Datenquelle) hängt von der Implementierung ab. Für das Yana Framework ist es eine benannte Datenquelle. Sie können benannte Datenbankverbindungen über das Administrationsmenü setzen.
readonly bool - no Sie können die Datenbank auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Tun Sie dies wenn Sie ein Datenbakviewer erstellen möchten, oder eine Anwendung auf CD-ROM.
Beschreibung

Ein Wurzelknoten, welcher die wichtigsten Eigenschaften und/oder Anforderungen spezifiziert. Diese können verwendet werden, wenn die Datenbank über ein Skript erstellt wird, oder ein Datenbankclient eine Verbindung herstellt.

Implementierung

Der Zeichensatz (charset) soll während des Anlegens der Datenbank gesetzt werden. Typische Zeichensätze sind: utf-8, ascii, iso-8859-1. Beachten Sie, dass einige DBMS verschiedene Schreibweisen desselben Zeichensatzes haben, oder Zeichensätze unterstützen, die andere DBMS nicht anbieten. Die Implementierung muss eine Liste von gültigen Zeichensätzen zur Verfügung stellen und automatisch auf die korrekte Schreibweise für das Ziel-DBMS abbilden. Die Implementierung kann einen Fehler melden, wenn ein nicht unterstützter Zeichensatz verwendet wird.
Die Datenquelle (datasource) ist im Allgemeinen ein Bezeichner für einen bestimmten Satz von Verbindungsparametern zu einer spezifischen Datenbank. Das kann eine JNDI Data-Source für Java, eine ODBC Data-Source für C#, oder eine andere benannte Datenquelle für eine andere Sprache sein.

Darstellung

Wenn eine Oberfläche für eine Datenbank dargestellt wird, kann die Implementierung das Attribut title der Datenbank als Überschrift wählen.

Element Description

  ELEMENT description (#PCDATA)
  
Beschreibung

Die Beschreibung dient zwei Zwecken: 1. der Offline-Dokumentation 2. der Online-Dokumentation.
Eine Beschreibung ist stets optional. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.

Darstellung

Der Formulargenerator kann die Beschreibung verwenden, um auf einer generierten Oberfläche kontextsensitive Hilfe, oder Zusatzinformation zur Verfügung zu stellen (abhängig von der Implementierung).

Element Include

  ELEMENT include (#PCDATA)
  
Beschreibung

Datenbankdefinitionen können in mehrere Dateien geteilt und rekursiv eingebunden werden. Zum Beispiel kann das notwendig sein, wenn Sie eine Referenz auf eine Tabelle erstellen möchten, welche an einer anderen Stelle definiert worden ist.

Die Liste der eingebundenen Dateien (Inlcudes) kann entweder Dateinamen, oder Bezeichner enthalten, welche durch die Anwendung zu Dateinamen umgewandelt werden können.
Beachten Sie, dass Sie nur Datenbankdefinitionen einbinden sollten, welche dieselbe Datenquelle (datasource) verwenden.

Implementierung

Die Kindknoten der Database-Tags der eingebundenen Dateien sollten in der Reihenfolge ihres Auftretens zum Datenbankknoten der Quelldatei hinzugefügt werden. Die Database-Elemente selbst sollen ignoriert werden. Wenn die eingebundene Datei weitere Dateien einbindet, dann sollten diese rekursiv behandelt werden. Sollte eine Datei mehrfach gelistet sein, so muss sie genau 1 Mal eingebunden werden. Falls eine Datei rekursiv eine weitere einbindet, welche jedoch bereits geladen wurde, so muss diese übersprungen und darf nicht zum zweiten Mal geladen werden. Eingebettete Dateien dürfen keine bereits vorhandenen Objekte redefinieren. z.B. darf eine eingeschlossene Datei nicht eine Tabellendefinition der Quelldatei überschreiben. Wenn ein bereits vorhandenes Element gefunden wird, muss ein Fehler gemeldet werden.

Element Sequence

  ELEMENT sequence (description?)
  ATTRIBUTE
       name        string
       start       integer
       increment   string
       min         integer
       max         integer
       cycle       bool
    
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Zahlenfolge identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
start integer - - Eine Zahlenfolge (Sequence) fängt immer mit einem Startwert an. Default ist der Minimalwert für aufsteigende, bzw. der Maximalwert für absteigende Zahlenfolgen.
Hinweis: der Startwert muss im Bereich der minimalen und maximalen Zahl liegen.
increment string - 1 Ein Inkrement (oder Schrittweite) spezifiziert die Zahl, welche zur Zahlenfolge addiert wird, zur Berechnung des Nachfolgers ihres aktuellen Wertes.
min integer - - Der Minimalwert ist eine Untergrenze für die Werte einer Zahlenfolge. Alle Werte müssen größer oder gleich dem Minimalwert sein. Der Minimalwert kann nicht größer als der Maximalwert sein. Default ist 1 für aufsteigende und PHP_INT_MIN für absteigende Zahlenfolgen.
max integer - - Der Maximalwert ist eine Obergrenze für die Werte einer Zahlenfolge. Alle Werte müssen kleiner oder gleich dem Maximalwert sein. Der Maximalwert kann nicht kleiner als der Minimalwert sein. Default ist PHP_INT_MAX für aufsteigende und -1 für absteigende Zahlenfolgen.
cycle bool - no Wenn eine Zahlenfolge ein Nummernkreis (cycle) ist und der Wert der Zahlenfolge eine Ober- oder Untergrenze erreicht, so wird diese zurückgesetzt auf den Minimalwert für eine aufsteigende, bzw. den Maximalwert für eine absteigende Zahlenfolge.
Beschreibung

Zahlenfolgen (Sequence) sind ganze Zahlen (Integer), in Verbindung mit einer Funktion zur Berechnung des Nachfolgers. Sie erfüllen verschiedene Aufgaben. Gewöhnlich werden sie verwendet, um eindeutige Id's automatisch zu generieren.
Beachten Sie, dass es implizite und explizite Zahlenfolgen gibt. Z.Bsp. wird implizit eine Zahlenfolge erzeugt, wenn eine Tabellenspalte mit der Eigenschaft Autoincrement angelegt wird. Implizite Zahlenfolgen dürfen nicht manuell definiert werden, da diese durch das DBMS selbst angelegt und verwaltet werden.
Beachten Sie auch, dass einige DBMS die Zahl 0 und den Wert NULL als gleich behandeln. Daher sollten Sie darauf achten, KEINE Zahlenfolge zu erzeugen, welche zu irgendeinem Zeitpunkt den Wert 0 annehmen kann. Außerdem können einige Anwendungen den Index 0 für Standardwerte reservieren (z.Bsp. ein Data-Warehouse).

Implementierung

Obwohl Zahlenfolgen Teil des SQL-2003 Standards sind, werden sie von den meisten Herstellern nicht unterstützt. Mit Ausnahme von PostgreSQL, wo diese ein bekanntes Feature darstellen. Sie können jedoch für andere DBMS simuliert werden.

Element Initialization

  ELEMENT initialization (#PCDATA)
  ATTRIBUTE
       dbms        string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
dbms string - generic Der Name des Ziel-DBMS. Der Wert "generic" bedeutet, dass die Definition für jedes DBMS zutreffend ist. Gewöhnlich wird das als Rückfalloption für DBMS verwendet, an welche Sie entweder beim Erstellen der Datenbankstruktur noch nicht gedacht haben, oder welche das fragliche Feature nicht unterstützen.
Beschreibung

SQL-Anweisungen zum Initialisieren der Datenbank, welche ausgeführt werden sollen, direkt nachdem die Datenbankstruktur publiziert wurde. Die Syntax kann entweder allgemein gültig (generic) sein oder DBMS-spezifisch.

Implementierung

Die folgenden Werte werden für das DBMS-Attribut vorgeschlagen: 'generic', 'db2', 'dbase', 'frontbase', 'informix', 'interbase', 'msaccess', mssql,'' mysql,'' oracle,'' postgresql,'' sybase,'' sqlite'.

Tabellen

Dieser Abschnitt definiert die Syntax aller erforderlichen Elemente, um die Struktur von Tabellen und damit verwandten Objekten innerhalb einer Datenbank zu beschreiben. Dies beinhaltet Spalten, Constraints, Trigger und Indexes.

Element Table

  ELEMENT table (description?, (grant* | primarykey | foreign* | trigger* |
                 constraint* | declaration | index)*)
  ATTRIBUTE
       name        string
       title       string
       readonly    bool
       inherits    string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name, welcher die Tabelle identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
title string - - Title ist eine Beschriftung, welche in der Nutzeroberfläche angezeigt werden sollte wenn das Objekt anzeigt wird.
Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
readonly bool - no Sie können die Tabelle auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden.
inherits string - - Name der Elterntabelle.
Beschreibung

Ein Tabelle ist eine Reihe von Spaltendefinitionen und Eigenschaften, welche alle Spalten der Tabelle gemeinsam haben, z. Bsp.: Trigger und Indexes.

Implementierung von Vererbung

Vererbung hat für Tabellen folgende Bedeutung: eine Kindtabelle AB erweitert die Struktur und Daten einer Elterntabelle A um die Elemente B. Alle Zeilen in AB besitzen sämtliche Spalten definiert in A + sämtliche Spalten aus B. B bleibt dabei unverändert. Wenn sich die Struktur von A ändert, ändert sich die Struktur von AB ebenso. Jedes Element von AB kann auch als ein Element von A interpretiert werden, aber nicht umgekehrt.
Technisch gesprochen: der Primärschlüssel der Kindtabelle ist ein Fremdschlüssel, der auf den Primärschlüssel der Elterntabelle verweist.
Dies ist ein Unterschied zu PostgreSQL, welches multiple Vererbung mit n Elterntabellen unterstützt - verbunden mit allen Konsequenzen und Problemen, welche dieses Verhalten verursacht.

Element Grant

  ELEMENT grant EMPTY
  ATTRIBUTE
       role        string
       user        string
       level       integer
       select      bool
       insert      bool
       update      bool
       delete      bool
       grant       bool
  
Attribute
Attribut Typ Pflicht Default Beschreibung
role string - - Die Rolle die ein Benutzer innerhalb einer Benutzergruppe spielt.
user string - - Die Gruppe zu der ein Benutzer gehört.
level integer - - Das Sicherheitslevel ist eine ganze Zahl zwischen 0 und 100. Dies kann als ein Wert von 0-100 Prozent verstanden werden, wobei 0 dem niedrigsten und 100 dem höchsten Zugang entspricht.
select bool - yes Gibt Auskunft ob der Nutzer Select-Abfragen auf dem Datenbankobjekt ausführen darf.
insert bool - yes Gibt Auskunft ob der Nutzer Insert-Anweisungen auf dem Datenbankobjekt ausführen darf.
update bool - yes Gibt Auskunft ob der Nutzer Update-Anweisungen auf dem Datenbankobjekt ausführen darf
delete bool - yes Gibt Auskunft ob der Nutzer Delete-Anweisungen auf dem Datenbankobjekt ausführen darf
grant bool - yes Gibt Auskunft ob der Nutzer seine Sicherheitsprivilegien vorübergehend anderen Nutzern gewähren darf.
Beschreibung

Die Rechteverwaltung bietet 3 Schichten, wovon in diesem Dokument alle optional sind. Eine Implementierung muss jedoch mindestens eine oder mehrere dieser Möglichkeiten umsetzen.

Nutzergruppen
wie Sales, Human Resources
Nutzerrollen
wie der Project Manager
Sicherheitslevel
eine ganze Zahl von 0 bis 100

In Analogie zu Datenbanken gibt es auch eine "grant"-Option, welche es Nutzern gestattet, Sicherheitsprivilegien, welche sie besitzen, vorübergehend anderen Nutzern zu gewähren. Folglich kann ein Manager alle seine Rechte auf einen Assistenten übertragen (und dies später widerrufen), während er im Urlaub ist.

Beispiele

Sie können festlegen, dass jeder Manager des Bereichs Human Resources mit einem Sicherheitslevel von 50 oder höher, einen neuen Mitarbeiter anlegen und Lohndaten einsehen kann, aber mindestens ein Manager der Gruppe Human Resources mit einem Sicherheitslevel von 80 erforderlich ist, um diese Daten nachträglich zu verändern.

Sie können auch einige der Angaben auslassen, um vielleicht jedem Nutzer mit einem Sicherheitslevel von 1 das Anzeigen eines Katalogformulars zu gestatten, oder allen Mitgliedern der Verkaufsabteilung Zugriff auf Verkaufsdaten zu erlauben.

Sie können genau festlegen, was ein Nutzer tun darf oder auch nicht: select (anzeigen), insert (erstellen), update (editieren), delete (löschen).

Beachten Sie, dass mehrere Grant-Elemente angegeben werden können, um mehrere Alternativen zu definieren. Z.Bsp. können Nutzer entweder ein Mitglied der Gruppe Sales, oder in der Rolle eines Geschäftsleiters sein, um Verkaufsinformationen abrufen und editieren zu können.

Implementierung

Wenn kein Grant-Element vorhanden ist, soll das Element öffentlich sein. Dies bedeutet, dass keine Sicherheitsüberprüfung durchgeführt wird. Wenn mindestens 1 Grant-Element existiert, darf keinem Benutzer erlaubt sein eine Operation auszuführen, sofern kein Grant existiert welcher ihm dies ausdrücklich erlaubt.

Das Yana Framework implementiert zusätzlich zu den genannten Einstellungen ein System von Anwendungsprofilen. Anwendungsprofile können verschiedene Tochtergesellschaften innerhalb Ihrer Firma definieren. Z.Bsp. Europa oder Asien. Falls Implementierungen, die Verwaltung mehrerer unabhängiger Mandanten auf einer gemeinsamen Installation unterstützen sollen, wird empfohlen ein vergleichbares System zu übernehmen.

Element Primarykey

  ELEMENT primarykey (#PCDATA)
  
Beschreibung

Der Primärschlüssel ist der Name einer einzelnen Spalte innerhalb der Tabelle, die eindeutige Werte besitzt und verwendet wird, um jede Zeile innerhalb der Tabelle zu identifizieren.

Implementierung

Die Software muss überprüfen, ob die angegebene Spalte existiert. Andernfalls muss ein Fehler gemeldet werden.
Jede Tabelle muss genau 1 Primärschlüssel besitzen. Zusammengesetzte Primärschlüssel (Compound Primary Keys) werden nicht unterstützt.

Element Declaration

  ELEMENT declaration (array | bool | color | date | enum | file | float |
                       html |image | inet | integer | list | mail |
                       password | range | reference | set | string | text |
                       time | timestamp |url)*
  
Beschreibung

Das Declaration-Element ist ein einfacher Container, der mehrere Spaltendefinitionen enthalten kann.

Element Trigger

  ELEMENT trigger (#PCDATA)
  ATTRIBUTE
       name        string
       dbms        string
       on          string
       insert      bool
       update      bool
       delete      bool
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string - - Ein eindeutiger Name welcher diesen Trigger identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
dbms string - generic Der Name des Ziel-DBMS. Der Wert "generic" bedeutet, dass die Definition für jedes DBMS zutreffend ist. Gewöhnlich wird das als Rückfalloption für DBMS verwendet, an welche Sie entweder beim Erstellen der Datenbankstruktur noch nicht gedacht haben, oder welche das fragliche Feature nicht unterstützen.
on string - before
before
Wird ausgelöst BEVOR die Anweisung ausgeführt wird.
after
Wird ausgelöst NACHDEM die Anweisung oder Transaktion erfolgreich ausgeführt wurde. Es wird nicht ausgelöst, falls die Anweisung einen Fehler verursacht hat.
instead
Wird ausgelöst ANSTATT der Anweisung. Die Anweisung selbst wird nicht ausgeführt. Diese Option wird nicht von allen DBMS unterstützt. Allerdings: sie kann bei Bedarf (mit einigen Einschränkungen) unter Verwendung von PHP-Code emuliert werden.
insert bool - no auslösen bei Insert-Anweisungen
update bool - no auslösen bei Update-Anweisungen
delete bool - no auslösen bei Delete-Anweisungen
Beschreibung

Trigger sind ein Feature von Datenbanksystemen, welches es erlaubt, auf bestimmte Datenbankereignisse mit der Ausführung von Code zu reagieren. Trigger werden durch Insert-, Update- oder Delete-Anweisungen, oder eine Kombination dieser, ausgelöst. Sie werden entweder vor (before), nachdem (after) oder anstatt (instead) der Anweisung ausgeführt. Nach dem Auslösen eines Triggers, wird der angegebene Code durch die Datenbank ausgeführt.

Die Syntax der Implementierung des Triggers hängt jedoch stark vom gewählten DBMS ab. Nicht alle DBMS unterstützen alle Features. Zum Beispiel: unterstützen nicht alle DBMS Trigger, die anstatt (instead) einer Anweisung ausgeführt werden und diese ersetzen.

Beachten Sie, dass ein Trigger eine benutzerdefinierte Funktion impliziert. Einige DBMS verlangen daher, dass diese Funktion explizit erzeugt und für den Trigger nur der Name der Funktion angeben wird. Andere DBMS erlauben, dass Sie den Funktionscode zusammen mit dem Trigger angeben.

Implementierung

Wenn ein Trigger eine Funktionalität verwendet, die durch das gewählte DBMS nicht unterstützt wird, wird dieses beim Versuch den Trigger zu erstellen einen Fehler melden. Die Implementierung selbst braucht dies nicht zu prüfen.

Trigger, welche die DBMS-Einstellung "generic" verwenden, müssen emuliert werden. In diesem Fall muss der Code durch die XDDL-kompatible Software, anstatt durch die Datenbank, ausgeführt werden. Die Implementierung kann die erforderliche Syntax für den Code selbst festlegen. Für diesen Fall wird empfohlen, dass das Attribut Code für derartige Trigger beschränkt wird auf gültige Callbacks (Funktions- oder Methodennamen). Das Yana Framework verlangt, dass das Attribut Code für emulierte Trigger ein gültiger Name einer nutzerdefinierten PHP-Funktion sein muss. Nähere Informationen zu diesem Thema finden Sie auch im Handbuch zur Datenbank-Schnittstelle.

Element Constraint

  ELEMENT constraint (#PCDATA)
  ATTRIBUTE
       name        string
       dbms        string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string - - Ein eindeutiger Name welcher diesen Constraint identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
dbms string - generic Der Name des Ziel-DBMS. Der Wert "generic" bedeutet, dass die Definition für jedes DBMS zutreffend ist. Gewöhnlich wird das als Rückfalloption für DBMS verwendet, an welche Sie entweder beim Erstellen der Datenbankstruktur noch nicht gedacht haben, oder welche das fragliche Feature nicht unterstützen.
Beschreibung

Ein Constraint ist ein boolescher Ausdruck, der jederzeit erfüllt sein muss, damit die Tabellenzeile gültig ist. Die Datenbank sollte dies sicherstellen. Für Datenbanken, welche dieses Feature nicht haben, kann der DBMS-Typ "generic" gesetzt werden, um dieses zu simulieren.

Implementierung

Wenn ein Constraint den DMBS-Typ "generic" verwendet und die XDDL-Implementierung nicht sicherstellen kann, dass die Datenbank das Feature unterstützt, dann muss diese den Constraint anstelle der Datenbank validieren. Die Implementierung kann die erforderliche Syntax für den Code selbst festlegen. Bei der Simulation dürfen Constraints auf Spalten äquivalent zu Constraints auf Tabellen behandelt werden. Das Yana Framework verwendet PHP als Sprache zur Definition generischer Constraints. Es liefert dazu ein assoziatives Array $ROW, welches Kopien der Werte der aktuellen Zeile beinhaltet. Die Schlüssel dieses Arrays entsprechen den Spaltennamen in Kleinbuchstaben.

Element Bool

  ELEMENT bool (description?, grant*, constraint*, default*)
  ATTRIBUTE
       name            string
       notnull         bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string yes - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - no Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Spalten vom Typ Boolean dürfen zwei Werte annehmen: True und False.

Implementierung

Boolesche Werte werden nicht von allen DBMS unterstützt , jedoch können diese durch die Verwendung von Integer-Spalten leicht simuliert werden.

Darstellung

Checkbox

Eingaben vom Typ Boolean werden beim Editieren als Checkbox repräsentiert. Beim Anzeigen der Spalte, wird eine Grafik eingefügt, welche den Status des Feldes repräsentiert.

HTML:

<input type="checkbox" value="true" name="{name}"/>
undefined <input type="radio" value="*" name="{name}"/>
null <input type="radio" value="true" name="{name}"/>
false <input type="radio" value="false" name="{name}"/>
<select name="{name}">
<option value="*">null</option>
<option value="true">true</option>
<option value="false">false</option>
</select>

Element Default

  ELEMENT default (#PCDATA)
  ATTRIBUTE
       dbms            string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
dbms string - generic Der Name des Ziel-DBMS. Der Wert "generic" bedeutet, dass die Definition für jedes DBMS zutreffend ist.
Beschreibung

Bei neu erstellten Datensätzen werden Spalten, für welche kein anderer Wert angegeben wurde, automatisch auf den Default-Wert gesetzt.

Implementierung

Der Typ des Werts hängt vom Typ der Spalte ab. Der physische Default-Wert hängt zusätzlich auch vom DBMS ab.
Ein gutes Beispiel ist der Datentyp Boolean, der durch PostgreSQL unterstützt wird und dessen physischer Default-Wert daher True oder False ist. Für MySQL wird diese Spalte jedoch als TinyInt gespeichert, mit den Default-Werden 1 oder 0.
Jedoch sind die DBMS-unabhängigen (generic) Default-Werte True oder False. Die Implementierung muss diese Werte automatisch umwandeln.

Element Color

  ELEMENT color (description?, grant*, constraint*, default*)
  ATTRIBUTE
       name            string
       notnull         bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - no Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Spalten vom Typ Color enthalten einen Farbwert in Hexadezimalschreibweise mit führendem '#'-Zeichen. Beispiel: #F0F0F0.

Implementierung

Diese Spalten können als Texte mit einer Länge 7 Zeichen umgesetzt werden.

Darstellung

colorpicker

Die Darstellung sollte als Input-Steuerelement erfolgen. Zusätzlich kann eine Eingabehilfe für Nutzer implementiert werden.

HTML5:

<input type="color" {required="notnull"} value="{default}" name="{name}"/>

Element Integer

  ELEMENT integer (description?, grant*, constraint*, default*)
  ATTRIBUTE
       name            string
       autoincrement   bool
       unsigned        bool
       fixed           bool
       length          integer
       notnull         bool
       unique          bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
autoincrement bool - no Autoincrement ist ein MySQL-Feature, welches jedoch für andere DBMS emuliert werden kann. Es kann jedoch nur auf Spalten vom Typ Integer angewendet werden. Sie sollten beachten, dass die Benutzereingabe Vorrang vor dem AutoIncrement hat, welches lediglich einen Default-Wert darstellt.
unsigned bool - no Eine Zahl ohne Vorzeichen muss stets ein positiver Wert sein. Das bedeutet, jeder Wert kleiner als 0 ist ungültig. Eine Implementierung muss einen Fehler melden, wenn für eine vorzeichenlose Spalte ein negativer Wert gegeben wird. (Beachten Sie, dass MySQL automatisch und ohne Warnung einen negativen Wert durch 0 ersetzt.)
fixed bool - no Setzt die Eigenschaft "zerofill" für MySQL. Für Zahlen fester Länge muss der Wert stets auf die definierte volle Anzahl an Ziffern erweitert werden, indem führende Nullen ergänzt werden. Falls das Attribut length nicht gesetzt ist, muss das Attribut fixed ignoriert werden.
length integer - - Die maximale Zahl an Ziffern.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
unique bool - no Ein Unique-Constraint bedeutet , dass die Spalte keinen Wert mehrfach enthalten darf. Beachten Sie, dass ein Unique-Constraint technisch einen Unique-Index auf dieser Spalte impliziert und umgekehrt.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - no Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Spalten vom Typ Integer können jede ganze Zahl enthalten, die durch die Datenbank und Programmiersprache angezeigt werden kann.

Implementierung

Die oberen und unteren Grenzen für Zahlenwerte hängen vom Typ des Systems ab. Im Allgemeinen: liegen auf 32-Bit-System die darstellbaren Zahlen im Bereich [-2^31, 2^31]. Für 64-Bit-Systeme können die Zahlen größer sein[-2^63, 2^63]. Allerdings nur, wenn sämtliche verwendete Software 64-Bit integer-Werte unterstützt.

Beachten Sie! 64-bit-und 32-Bit- Anwendungen müssen nicht kompatibel sein. Besonders, wenn Sie einen 64-Bit-Datenbankserver mit einer 32-Bit-Anwendung oder umgekehrt verwenden. Seien Sie gewarnt, dass ein Zahlenüberlauf oder -unterlauf auftreten kann, wenn eine große 64-Bit in eine kleine 32-Bit Zahl umgewandelt wird. Beachten Sie, dass das für Datums- und Zeitangaben ebenso gilt!

Darstellung

Input

Einzeilige Texte und Zahlen werden beim Editieren der Spalte als Inputfeld dargestellt. Ist die Spalte nicht editierbar, wird der Inhalt als Textzeile dargestellt.

HTML5:

<input type="number" step="1" {required="notnull"} name="{name}"/>

Element Float

  ELEMENT float (description?, grant*, constraint*, default*)
  ATTRIBUTE
       name            string
       unsigned        bool
       length          integer
       precision       integer
       notnull         bool
       unique          bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
unsigned bool - no Eine Zahl ohne Vorzeichen muss stets ein positiver Wert sein. Das bedeutet, jeder Wert kleiner als 0 ist ungültig. Eine Implementierung muss einen Fehler melden, wenn für eine vorzeichenlose Spalte ein negativer Wert gegeben wird. (Beachten Sie, dass MySQL automatisch und ohne Warnung einen negativen Wert durch 0 ersetzt.)
length integer - - Die maximale Zahl an Ziffern.
precision integer - - Definiert die Länge der Nachkommastellen. Wenn vorhanden, muss das Attribut length ebenfalls gesetzt sein. Die maximale vollen Stellen ist: length - precision. Beachten Sie, dass der Wert precision nicht größer sein darf als das Attribut length.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
unique bool - no Ein Unique-Constraint bedeutet , dass die Spalte keinen Wert mehrfach enthalten darf. Beachten Sie, dass ein Unique-Constraint technisch einen Unique-Index auf dieser Spalte impliziert und umgekehrt.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - no Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Spalten vom Typ Float können jede Zahl enthalten, die durch die Datenbank und Programmiersprache angezeigt werden kann. Dabei kann es sich entweder um ganze Zahlen, Fließkommazahlen, oder Festpunktzahlen (mit fester Anzahl Nachkommastellen) handeln.

Implementierung

Die oberen und unteren Grenzen für Werte hängen vom Typ des Systems ab. Beachten Sie, dass für Fließkommazahlen die "maximale Länge" die maximale Anzahl an Ziffern, inklusive der gebrochenen Stellen, meint. Daher werden Sie für sehr große oder sehr kleine Zahlen Genauigkeit verlieren. Für Festkommazahlen werden Maximum und Minimum um die Anzahl der für die Darstellung der Nachkommastellen reservierten Dezimalstellen reduziert.

Beachten Sie! 64-bit-und 32-Bit- Anwendungen müssen nicht kompatibel sein. Besonders, wenn Sie einen 64-Bit-Datenbankserver mit einer 32-Bit-Anwendung oder umgekehrt verwenden. Seien Sie gewarnt, dass ein Zahlenüberlauf oder -unterlauf auftreten kann, wenn eine große 64-Bit in eine kleine 32-Bit Zahl umgewandelt wird. Beachten Sie, dass das für Datums- und Zeitangaben ebenso gilt!

Darstellung

Input

Einzeilige Texte und Zahlen werden beim Editieren der Spalte als Inputfeld dargestellt. Ist die Spalte nicht editierbar, wird der Inhalt als Textzeile dargestellt.

HTML5:

<input type="number" {required="notnull"} name="{name}"/>

Element Range

  ELEMENT range (description?, grant*, constraint*, default*)
  ATTRIBUTE
       name            string
       notnull         bool
       unique          bool
       readonly        bool
       min             float
       max             float
       step            float
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
unique bool - no Ein Unique-Constraint bedeutet , dass die Spalte keinen Wert mehrfach enthalten darf. Beachten Sie, dass ein Unique-Constraint technisch einen Unique-Index auf dieser Spalte impliziert und umgekehrt.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
min float ja - Kleinster erlaubter Wert.
max float ja - Größter erlaubter Wert.
step float - 1.0 Minimale Schrittweite.
title string - - Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Spalten vom Typ Range können jede Zahl enthalten, die durch die Datenbank und Programmiersprache angezeigt werden kann. Dabei kann es sich entweder um ganze Zahlen, Fließkommazahlen, oder Festpunktzahlen (mit fester Anzahl Nachkommastellen) handeln.

Implementierung

Dieser Typ muss analog zu Spalten vom Typ Float behandelt werden. Die Angabe der Attribute "min" und "max" impliziert einen oder mehrere Constraints. Der Wert der Spalte darf nicht kleiner als "min" und nicht größer als "max" sein. Das Attribut "max" darf nicht kleiner als "min" sein. Die Spalte muss mindestens 2 gültige Werte erlauben. Das heißt: "min" + "step" muss kleiner oder gleich "max" sein. Der Wert "max" - "min" sollte ein Vielfaches von "step" betragen. Der Wert "step" darf nicht negativ sein.

Darstellung

Dargestellt werden Zahlen dieses Typs als horizontaler Schieberegler ("imprecise number-input control"). Die Wahl der genauen Umsetzung darf dem Client vorbehalten werden.

HTML5:

<input type="range" {required="notnull"} min="{min}" max="{max}" step="{step}" name="{name}"/>

Element String

  ELEMENT string (description?, grant*, constraint*, default*)
  ATTRIBUTE
       name            string
       length          integer
       notnull         bool
       unique          bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
length integer - - Die maximale Zahl an Zeichen.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
unique bool - no Ein Unique-Constraint bedeutet , dass die Spalte keinen Wert mehrfach enthalten darf. Beachten Sie, dass ein Unique-Constraint technisch einen Unique-Index auf dieser Spalte impliziert und umgekehrt.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - - Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Spalten vom Typ String können eine einzelne Linie Text enthalten.

Implementierung

Beachten Sie, dass String-Werte keine Zeilenumbrüche enthalten dürfen. Dabei handelt es sich um die Zeichen \f, \r und \n. Aus Sicherheitsgründen dürfen Werte das Zeichen \#0 nicht enthalten.

Darstellung

Input

Einzeilige Texte und Zahlen werden beim Editieren der Spalte als Inputfeld dargestellt. Ist die Spalte nicht editierbar, wird der Inhalt als Textzeile dargestellt.

HTML5:

<input type="text" maxlength="{length}" {required="notnull"} name="{name}"/>

Element Mail

  ELEMENT mail (description?, grant*, constraint*, default*)
  ATTRIBUTE
       name            string
       length          integer
       notnull         bool
       unique          bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
length integer - - Die maximale Zahl an Zeichen.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
unique bool - no Ein Unique-Constraint bedeutet , dass die Spalte keinen Wert mehrfach enthalten darf. Beachten Sie, dass ein Unique-Constraint technisch einen Unique-Index auf dieser Spalte impliziert und umgekehrt.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - - Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Spalten vom Typ Mail können jede gültige E.-Mailadresse enthalten.

Implementierung

Mails werden als Werte vom Typ String implementiert. Die Syntax von E.-Mailadressen wird in RFC 822 spezifiziert. Für PHP-Implementierungen wird zur Validierung von E.-Mailadressen folgender Code empfohlen: filter_var($email, FILTER_VALIDATE_EMAIL) === true. Andere Implementierungen können den folgenden regulären Ausdruck verwenden: [\w\d-_\.]{1,}\@[\w\d-_\.]{2,}\.[\w\d-_\.]{2,}.

Darstellung

HTML-Code

Beim Editieren wird die Spalte als Inputfeld dargestellt. Dies ist identisch zur Darstellung eines Strings.

Eingaben vom Datentyp "mail" sollten bei der Darstellung im Browser automatisch verschlüsselt werden, um Datendiebstahl zu erschweren. Dies gilt grundsätzlich für alle angezeigten E.-Mailadressen. Die Umsetzung erfolgt im Yana Framework automatisch in der Darstellungsschicht. Eingriffe von Hand sich nicht erforderlich.

HTML5:

<input type="email" maxlength="{length}" {required="notnull"} name="{name}"/>

Element Url

  ELEMENT url (description?, grant*, constraint*, default*)
  ATTRIBUTE
       name            string
       length          integer
       notnull         bool
       unique          bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
length integer - - Die maximale Zahl an Zeichen.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
unique bool - no Ein Unique-Constraint bedeutet , dass die Spalte keinen Wert mehrfach enthalten darf. Beachten Sie, dass ein Unique-Constraint technisch einen Unique-Index auf dieser Spalte impliziert und umgekehrt.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - - Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Spalten vom Typ URL entsprechen dem Typ "String", mit dem Unterschied, dass geprüft wird ob die Eingabe eine syntaktisch korrekte URL ist.

Implementierung

URLs werde als Werte vom Typ String implementiert. Die Syntax von URIs ist in RFC 3986 spezifiziert. Für PHP-Implementierungen wird zur Validierung folgender Code empfohlen: filter_var($url, FILTER_VALIDATE_URL) === true.

Darstellung

Input

Einzeilige Texte und Zahlen werden beim Editieren der Spalte als Inputfeld dargestellt. Ist die Spalte nicht editierbar, wird der Inhalt als Textzeile dargestellt.

HTML5:

<input type="url" {required="notnull"} name="{name}"/>

Element Password

  ELEMENT password (description?, grant*, constraint*, default*)
  ATTRIBUTE
       name            string
       notnull         bool
       unique          bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
unique bool - no Ein Unique-Constraint bedeutet , dass die Spalte keinen Wert mehrfach enthalten darf. Beachten Sie, dass ein Unique-Constraint technisch einen Unique-Index auf dieser Spalte impliziert und umgekehrt.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - - Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Eine Spalte vom Typ Password wird verwendet, um verschlüsselte Passwörter zu verwalten.

Implementierung

Passwörter sind Hashwerte. Die Werte müssen aus der Nutzereingabe mit einem Hash-Algorithmus, wie MD5, berechnet werden. Passwörter dürfen nicht als Klartext gespeichert sein.

Darstellung

Password

Passwörter werden nicht als Text angezeigt, sondern als Input-Element vom Typ "password".

HTML5:

<input type="password" {required="notnull"} name="{name}"/>

Element Inet

  ELEMENT inet (description?, grant*, constraint*, default*)
  ATTRIBUTE
       name            string
       notnull         bool
       unique          bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
unique bool - no Ein Unique-Constraint bedeutet , dass die Spalte keinen Wert mehrfach enthalten darf. Beachten Sie, dass ein Unique-Constraint technisch einen Unique-Index auf dieser Spalte impliziert und umgekehrt.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - - Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Spalten vom Typ Inet bieten die Möglichkeit, automatisch die IP-Adresse des Nutzers zu speichern.

Implementierung

Spalten vom Typ Inet werden als Werte vom Typ String implementiert. Die Implementierung muss IPv4 und IPv6 unterstützen. Die Syntax von IPv6 wird in RFC 2460 spezifiziert.

Für PHP-Implementierungen wird zur Validierung folgender Code empfohlen: filter_var($inet, FILTER_VALIDATE_IP) === true. Andere Implementierungen können die folgenden regulären Ausdrücke verwenden:

IPv4:
\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}
IPv6:
[a-f0-9]{1,4}:[a-f0-9]{1,4}:[a-f0-9]{1,4}:[a-f0-9]{1,4}:[a-f0-9]{1,4}:[a-f0-9]{1,4}:[a-f0-9]{1,4}:[a-f0-9]{1,4}
Darstellung

Input

In der Regel werden Spalten dieses Typs nicht als editierbar markiert. Falls doch, wird ein Inputfeld angezeigt.

HTML5:

<input type="text" {required="notnull"} name="{name}"/>

Element Text

  ELEMENT text (description?, grant*, constraint*)
  ATTRIBUTE
       name            string
       length          integer
       notnull         bool
       unique          bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
length integer - - Die maximale Zahl an Zeichen.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
unique bool - no Ein Unique-Constraint bedeutet , dass die Spalte keinen Wert mehrfach enthalten darf. Beachten Sie, dass ein Unique-Constraint technisch einen Unique-Index auf dieser Spalte impliziert und umgekehrt.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - - Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Spalten vom Typ Text können mehrere Textzeilen enthalten. Ihre Länge ist nicht begrenzt.

Implementierung

Beachten Sie, dass die Länge aus technischen Gründen beschränkt sein kann. Der physische Datentyp hängt vom gewählten DBMS ab. Darüber hinaus kann das DBMS das Erstellen eines Index auf einer Textspalte verweigern, oder einen Volltextindex mit spezifischen Eigenschaften erstellen.

Aus Sicherheitsgründen dürfen Werte das Zeichen \#0 nicht enthalten.

Alle für HTML reservierten Zeichen müssen maskiert werden. Zusätzlich kann die Implementierung Ein- und Ausgabefilter definieren. Diese können zum Beispiel verwendet werden, um Smilies umzuwandeln und/oder Spam und Floods zu unterbinden.

Zum Beispiel implementiert, das Yana Framework mehrere Filter, um offensichtlichen Vandalismus zu verhindern.

Darstellung

Textarea

Mehrzeilige Texte werden beim Editieren als Textareafelder dargestellt. Ist die Spalte nicht editierbar, wird der Inhalt als Fließtext dargestellt. Bei zu langen Texten werden Scrollbalken erzeugt (CSS: "overflow: auto").

HTML5:

<textarea maxlength="{length}" {required="notnull"} name="{name}"/>

Element Html

  ELEMENT html (description?, grant*, constraint*)
  ATTRIBUTE
       name            string
       length          integer
       notnull         bool
       unique          bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
length integer - - Die maximale Zahl an Zeichen.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
unique bool - no Ein Unique-Constraint bedeutet , dass die Spalte keinen Wert mehrfach enthalten darf. Beachten Sie, dass ein Unique-Constraint technisch einen Unique-Index auf dieser Spalte impliziert und umgekehrt.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - - Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Spalten vom Typ HTML können mehrere Zeilen Hypertext im XHTML-Format enthalten.

Implementierung

Sie sollten bedenken, dass Hypertext Tags und Entitäten enthalten kann. Die Bestimmung der wahren Länge eines solchen Textes kann heikel sein.

Es dürfen keine Dateien (wie zum Beispiel Grafiken) an den HTML-Inhalt angehängt oder eingebettet werden. Jedoch darf die Spalte einen Tag enthalten, welcher auf eine Datei verweist, welche an anderer Stelle gespeichert ist.

Aus Sicherheitsgründen dürfen Werte das Zeichen \#0 nicht enthalten.

Zusätzlich kann die Implementierung Ein- und Ausgabefilter definieren. Zum Beispiel um XSS-Angriffe und Vandalismus zu verhindern.

Darstellung

Um HTML-Spalten zu editieren, kann die Implementierung einen eingebetteten HTML-Editor verwenden. Eigenschaften und Verhalten dieses Editors sind nicht spezifiziert. Für die Ausgabe müssen HTML-Spalten als interpretierter Hypertext, gemäß den Anforderungen des XHTML 1.0 Standards, oder eines Nachfolgers dieses Standards (z.Bsp. HTML 5), dargestellt werden.

Element Date

  ELEMENT date (description?, grant*, constraint*, default*)
  ATTRIBUTE
       name            string
       notnull         bool
       unique          bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
unique bool - no Ein Unique-Constraint bedeutet , dass die Spalte keinen Wert mehrfach enthalten darf. Beachten Sie, dass ein Unique-Constraint technisch einen Unique-Index auf dieser Spalte impliziert und umgekehrt.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - - Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Spalten vom Typ Date werden verwendet, um ein Datum ohne Zeit, oder Zeitzone zu verwalten.

Implementierung

Der physische Datentyp hängt vom gewählten DBMS ab. Für DBMS, welche diesen Typ nicht unterstützten, kann dies über den Typ Integer simuliert werden.

Darstellung

Select

Beim Editieren können Selectboxen angezeigt werden, welche die Eingabe erleichtern.

Eingaben werden als Text dargestellt. Die Darstellung kann je nach gewählter Landessprache abweichen.

HTML5:

<input type="date" {required="notnull"} name="{name}"/>

Element Time

  ELEMENT time (description?, grant*, constraint*, default*)
  ATTRIBUTE
       name            string
       notnull         bool
       unique          bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
unique bool - no Ein Unique-Constraint bedeutet , dass die Spalte keinen Wert mehrfach enthalten darf. Beachten Sie, dass ein Unique-Constraint technisch einen Unique-Index auf dieser Spalte impliziert und umgekehrt.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - - Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Spalten vom Typ Time werden verwendet, um ein Datum mit Zeit und Zeitzone zu verwalten.

Implementierung

Der physische Datentyp hängt vom gewählten DBMS ab. Für DBMS, welche diesen Typ nicht unterstützten, kann dies über den Typ Integer simuliert werden.

Darstellung

Select

Beim Editieren können Selectboxen angezeigt werden, welche die Eingabe erleichtern.

Eingaben werden als Text dargestellt. Die Darstellung kann je nach gewählter Landessprache und Zeitzone abweichen.

HTML5:

<input type="datetime" {required="notnull"} name="{name}"/>

Element Timestamp

  ELEMENT timestamp (description?, grant*, constraint*, default*)
  ATTRIBUTE
       name            string
       notnull         bool
       unique          bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
unique bool - no Ein Unique-Constraint bedeutet , dass die Spalte keinen Wert mehrfach enthalten darf. Beachten Sie, dass ein Unique-Constraint technisch einen Unique-Index auf dieser Spalte impliziert und umgekehrt.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - - Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Spalten vom Typ Timestamp werden verwendet, um ein Datum mit Zeit in UTC zu verwalten.

Dieser Typ ist identisch zu Time, abgesehen von der technischen Umsetzung.

Implementierung

Der physische Datentyp hängt vom gewählten DBMS ab. Gewöhnlich wird der Wert als ganze Zahl gespeichert und zurückgegeben.

Beachten Sie, dass es bei einigen Betriebssystemen Probleme mit negativen Zeitstempeln geben kann, beispielsweise auf älteren Win32-Systemen.

Achten Sie darauf, nicht den Wert 0 (1.1.1970) mit NULL (undefiniert) zu verwechseln.

Darstellung

Select

Beim Editieren können Selectboxen angezeigt werden, welche die Eingabe erleichtern.

Eingaben werden als Text dargestellt. Die Darstellung kann je nach gewählter Landessprache und Zeitzone abweichen.

HTML5:

<input type="datetime-local" {required="notnull"} name="{name}"/>

Element Enum

  ELEMENT enum (description?, grant*, constraint*, default*, option+)
  ATTRIBUTE
       name            string
       notnull         bool
       unique          bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
unique bool - no Ein Unique-Constraint bedeutet , dass die Spalte keinen Wert mehrfach enthalten darf. Beachten Sie, dass ein Unique-Constraint technisch einen Unique-Index auf dieser Spalte impliziert und umgekehrt.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - - Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Der Datentyp Enum ist ein "Aufzählungstyp" (Enumeration). Der Liste der gültigen Werte kann über Option-Elemente vorgeben werden.

Beachten Sie, dass der Default-Wert (falls angegeben) ein gültiges Element des Aufzählungstyps sein muss.

Implementierung

Aufzählungstypen werden als Texte gespeichert. Der Wert entspricht dem Attribut value der gewählten Option.

Darstellung

Select

Beim Editieren wird eine Select-Box erzeugt. Alternativ können Radio-Buttons verwendet werden. Die Elemente entsprechen den Option-Elementen des Tags.

HTML5:

<select name="{name}">
<option value="">null</option>
<option value="1">1</option>
<option value="2">2</option>
...
<option value="n">n</option>
</select>

Element Option

  ELEMENT option (#PCDATA)
  ATTRIBUTE
       value        string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
value string - - Text oder Integer-Wert für diese Option.
Beschreibung

Eine Option entspricht einem gültigen Element eines Aufzählungstyps. Diese hat eine Beschreibung als Text (pcdata) und einen Wert. Nur der Wert wird in der Datenbank gespeichert. Die Beschreibung (pcdata) wird nur in der Nutzeroberfläche (anstatt des Werts) angezeigt.

Die Beschreibung stellt die Option in lesbarem Text dar. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.

Wenn ein für den Aufzählungstyp ungültiger oder undefinierter Wert in der Datenbank gefunden wird, muss in der Nutzeroberfläche genau der gespeicherte Wert anzeigt werden, ohne diesen umzuwandeln. Die Implementierung kann zusätzlich einen Fehler melden.

Element Set

  ELEMENT set (description?, grant*, constraint*, default*, option+)
  ATTRIBUTE
       name            string
       notnull         bool
       unique          bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
unique bool - no Ein Unique-Constraint bedeutet , dass die Spalte keinen Wert mehrfach enthalten darf. Beachten Sie, dass ein Unique-Constraint technisch einen Unique-Index auf dieser Spalte impliziert und umgekehrt.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - - Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Der Datentyp "set" entspricht dem Typ "enum", gestattet es jedoch, mehrere Werte auszuwählen.

Beachten Sie, dass der Default-Wert (falls angegeben) ein gültiges Element des Aufzählungstyps sein muss.

Implementierung

Der physische Datentyp hängt vom gewählten DBMS ab. Einige DBMS bieten eine native Unterstützung für diesen Typ. Diese sollte verwenden werden, wenn sie verfügbar ist. Andernfalls können die Eingaben als durch Kommata getrennte Texte gespeichert werden. Die Werte entsprechen den Werten der gewählten Optionen.

Darstellung

Checkbox

Beim Editieren wird eine Liste von Checkboxes erzeugt. Alternativ kann eine Select-Box verwendet werden, welche die Auswahl mehrerer Optionen gestattet. In beiden Fällen entsprechen die Werte und Beschriftungen den Option-Elementen des Tags.

HTML5:

<label><input type="checkbox" name="{name}[]" value="1"> 1 </label>
<label><input type="checkbox" name="{name}[]" value="2"> 2 </label>
...
<label><input type="checkbox" name="{name}[]" value="n"> n </label>
<select multiple="multiple" name="{name}">
<option value="">null</option>
<option value="1">1</option>
<option value="2">2</option>
...
<option value="n">n</option>
</select>

Element List

  ELEMENT list (description?, grant*, constraint*)
  ATTRIBUTE
       name            string
       notnull         bool
       unique          bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
unique bool - no Ein Unique-Constraint bedeutet , dass die Spalte keinen Wert mehrfach enthalten darf. Beachten Sie, dass ein Unique-Constraint technisch einen Unique-Index auf dieser Spalte impliziert und umgekehrt.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - - Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Spalten vom Typ List sind numerische Arrays die als Werte Zeichenketten enthalten.

Implementierung

PostgreSQL bietet native Unterstützung für Arrays. Für andere DBMS muss dieses Feature simuliert werden. Dies kann implementiert werden, indem die Werte als serialisierte Zeichenfolge oder durch Kommata getrennte Aufzählung der Elemente gespeichert werden. Diese Zeichenfolge sollte, wenn sie geladen wird, deserialisiert, und als Array zurückgegeben werden.

Darstellung

Select

Listen werden beim Editieren als Liste von Inputelementen dargestellt. Es wird zusätzlich ein Steuerelement zum Entfernen und Hinzufügen von Einträgen angezeigt.

Ist das Element nicht editierbar, so werden seine Elemente als Liste aufgezählt.

Die Listendarstellungen können nummeriert sein.

Element Array

  ELEMENT array (description?, grant*, constraint*)
  ATTRIBUTE
       name            string
       notnull         bool
       unique          bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
unique bool - no Ein Unique-Constraint bedeutet , dass die Spalte keinen Wert mehrfach enthalten darf. Beachten Sie, dass ein Unique-Constraint technisch einen Unique-Index auf dieser Spalte impliziert und umgekehrt.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - - Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Eine Spalte vom Typ Array ist (möglicherweise mehrdimensionales) Array von Zeichenfolgen.

Implementierung

Für die meisten DBMS muss dieses Feature simuliert werden. Dies kann implementiert werden, indem die Werte als serialisierte Zeichenfolge gespeichert werden. Diese Zeichenfolge sollte, wenn sie geladen wird, deserialisiert, und als Array zurückgegeben werden. Für diesen Fall wird empfohlen, die Zeichenfolge in JSON zu kodieren.

Darstellung

Array

Arrays werden beim Editieren als Paare von Schlüsseln und Werten dargestellt. Es wird zusätzlich ein Steuerelement zum Entfernen und Hinzufügen von Einträgen angezeigt.

Ist das Element nicht editierbar, so werden seine Elemente als mehrdimensionale Listen aufgezählt. Schlüssel und Werte werden optisch voneinander getrennt dargestellt. Die Darstellung kann als aufklappbares Baummenü erfolgen.

Element File

  ELEMENT file (description?, grant*, constraint*)
  ATTRIBUTE
       name            string
       notnull         bool
       maxsize         integer
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
maxsize integer - - Die maximale Größe der Datei in Bytes.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - - Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Der Datentyp "file" dient dem Speichern von Dateien ("binary large objects").

Implementierung

Die Dateien selbst sollten nach dem Upload aus Gründen der besseren Performance im Dateisystem verbleiben. Um Speicherplatz zu sparen, kann eine Komprimierung (z.Bsp. GZip) verwendet werden. Die Komprimierung sorgt außerdem dafür, dass die auf dem Server gespeicherten Dateien nicht ausführbar sind und ein potentieller Angreifer den Upload nicht missbrauchen kann, um Schadcode zu übertragen.

Die Datei sollte aus Sicherheitsgründen so abgespeichert werden, dass diese für den Client nicht direkt abrufbar ist. Beim Download der Datei sollte diese automatisch entpackt werden, so dass der Nutzer keine Nachteile aus der Komprimierung erfährt und auch kein Dekomprimierungsprogramm installiert haben muss. Um trotzdem einen schnelleren Download zu gewährleisten, können die Daten, falls der Browser des Nutzers diese Funktionalität anbietet, automatisch als komprimierter Datenstrom übertragen werden. Der Browser übernimmt das Entpacken selbstständig. Ein Eingreifen von Hand ist nicht erforderlich.

Darstellung

Array

Beim Editieren wird ein Uploadfeld zum Hochladen einer neuen Datei und ein Link für den Download der aktuell gespeicherten Datei angezeigt. Die Implementierung kann für Dateien deren Mime-Type bekannt ist eine Vorschau anbieten.

Element Image

  ELEMENT image (description?, grant*, constraint*)
  ATTRIBUTE
       name            string
       notnull         bool
       width           integer
       height          integer
       ratio           bool
       background      string
       maxsize         integer
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
width integer - - Die Breite des Bildes in Pixel
height integer - - Die Höhe des Bildes in Pixel
ratio bool - no Betrifft nur den Prozess des Anpassens der Größe von Bildern, für welche die Attribute height und width angegeben sind. In allen anderen Situationen muss das Attribut ignoriert werden. Hat dieses Attribut den Wert "yes", muss das Seitenverhältnis des Bildes bei der Veränderung der Größe beibehalten werden. Hat es den Wert "no", muss das Bild auf die angegebene Größe gestreckt oder gestaucht werden.
background hex-value - - Betrifft nur den Prozess des Anpassens der Größe von Bildern, für welche das Attribut ratio auf "yes" gesetzt ist und die Attribute height und width angegeben sind. In diesem Fall können Sie die Hintergrundfarbe angeben. In allen anderen Situationen muss das Attribut ignoriert werden. Der Wert muss ein hexadezimaler Farbwert sein. Beispiel: #f0a080
maxsize integer - - Die maximale Größe des Bildes in Bytes.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - - Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Spalten des Typs Image sind Dateien (binary large objects). Diese müssen eine Grafik eines unterstützten Typs sein und sollten auf der Nutzeroberfläche als Bild angezeigt werden können.

Implementierung

Die Grafikdatei muss beim Upload automatisch geprüft und gegebenenfalls angepasst werden. Sollte die gegebene Datei keine gültige Grafik sein, muss die Implementierung einen Fehler melden. Die Anpassung der Grafik muss gemäß den Attributen "width", "height", "ratio" und "background" erfolgen. Die Größe der Grafik wird auf die angegebene Höhe und Breite angepasst. Falls das Attribut "ratio" auf "no" gesetzt ist und Breite und Höhe gegeben sind, so erfolgt eine asymmetrische Anpassung der Bildgröße auf exakt die angegeben Werte. Andernfalls wird das Bild in Höhe und/oder Breite so angepasst, dass die Bildsymmetrie (also das Seitenverhältnis) erhalten bleibt. Sollte durch diese Änderung ein leerer Teil der Canvas entstehen, so wird dieser Teil mit einer Hintergrundfarbe gefüllt. Die Hintergrundfarbe wird über das Attribut "background" angegeben. Sollte keine Hintergrundfarbe gegeben sein, so kann die Software selbstständig entscheiden, welche Farbe verwendet wird.

Beachten Sie: nicht alle Grafiken sind geeignet für die Darstellung in einem Browser. Zum Beispiel haben typischerweise viele Browser (und andere Programme) Probleme mit der Darstellung von Grafiken, welche CMYK-kodierte Farben verwenden.

Grafikdateien sollten aus Gründen der Performance außerhalb der Datenbank gespeichert werden. Eine Komprimierung von Bitmapgrafiken ist in der Regel nicht sinnvoll und sollte vermieden werden.

Eine Liste der gültigen Grafikformate und/oder Regeln für deren Interpretation werden in diesem Dokument nicht spezifiziert. Die Behandlung von Vektorgrafiken wird in diesem Dokument nicht spezifiziert.

Darstellung

Uploadfeld

Spalten vom Datentyp Image werden als Vorschau (Thumbnail) mit einem Uploadfeld zum Einfügen oder Ersetzen der gespeicherten Grafik dargestellt. Beim Klick auf das Thumbnail sollte die vollständige Grafik angezeigt werden. Für die Erstellung der Vorschau sollte die Implementierung ebenfalls die Attribute ratio und background berücksichtigen.

Element Reference

  ELEMENT reference (description?, grant*, constraint*, default*)
  ATTRIBUTE
       name            string
       table           string
       column          string
       label           string
       notnull         bool
       unique          bool
       readonly        bool
       title           string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diese Spalte identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
table string - - Name der Zieltabelle.
column string - - Der Name der Zielspalte, welche die Werte der Referenz enthält (Werte müssen eindeutig sein). Die Werte in in dieser Spalte werden als Wert der Referenz gespeichert.
label string - - Der Name einer Zielspalte, welche die Beschriftungen enthält (Werte sollten eindeutig sein). Die Spalte sollte eine lesbare Beschreibung enthalten, welche dem User angezeigt wird.
notnull bool - no Eine Spalte, die mit not-null definiert ist, darf keine undefinierten (NULL-)Werte enthalten.
unique bool - no Ein Unique-Constraint bedeutet , dass die Spalte keinen Wert mehrfach enthalten darf. Beachten Sie, dass ein Unique-Constraint technisch einen Unique-Index auf dieser Spalte impliziert und umgekehrt.
readonly bool - no Sie können die Spalte auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Hinweis: Zeilen können weiterhin hinzugefügt oder gelöscht werden, jedoch darf die Spalte nicht aktualisiert werden.
title string - - Ein Text welcher in der Nutzeroberfläche zur Beschriftung des mit der Spalte verbundenen Steuerelementes verwendet werden kann. Beachten sie, dass der Text ein Platzhalter sein darf, welcher für die angezeigte Sprache übersetzt wird.
Beschreibung

Spalten vom Typ Reference werden verwendet um Fremdschlüssel zu repräsentieren. Der echte Typ der Spalte hängt vom Typ der Zielspalte ab.

Implementierung

Eine Referenz impliziert nicht automatisch einen Foreign-Key-Constraint.

Nur der Wert wird in der Datenbank gespeichert. Der physische Typ und die Eigenschaften der Spalte werden daher von der in die Zielspalte geerbt. Wenn der physische Typ der Zielspalte sich ändert, muss sich der physische Typ der Referenzspalte auch ändern. Wenn die Zielspalte keinen passenden Typ hat, muss die Implementierung einen Fehler melden.

Darstellung

Selectbox

Beim Editieren wird eine Select-Box erzeugt. Das Menü wird mit den Einträgen der verlinkten Tabelle aufgefüllt. Die Beschriftungen werden aus der Spalte "label" und die Werte aus der Spalte "column" in der Zieltabelle entnommen.

Element Foreign

  ELEMENT foreign (key+)
  ATTRIBUTE
       name            string
       table           string
       match           string
       ondelete        string
       onupdate        string
       deferrable      bool
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string - - Ein eindeutiger Name welcher diesen Foreign-Key-Constraint identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
table string ja - Name der Zieltabelle.
match string - simple full | partial | simple
ondelete string - no-action no-action | restrict | cascade | set-null | set-default
onupdate string - no-action no-action | restrict | cascade | set-null | set-default
deferrable bool - no Deferrable bedeutet, dass der DBS bis zum Ende der Transaktion warten sollte, bevor hinzugefügte oder aktualisierte Fremdschlüssel geprüft werden.
Das wird in Situationen verwendet, in denen Daten innerhalb einer Transaktion sowohl in die Eltern- als auch in die Kindtabelle eingefügt werden, oder wenn kreisförmige Referenzen erzeugt werden (sofern das DBMS dies unterstützt).
Beschreibung

Fremdschlüssel dienen dazu, referentielle Integrität zwischen Tabellen zu gewährleisten. Dieses Feature wird nicht von allen DBMS unterstützt. Die Implementierung kann dieses Feature emulieren.

Jeder Fremdschlüssel besteht aus mindestens einer Quelle und einem Ziel. Beachten Sie, dass die Datentypen der Quellspalten eines Fremdschlüssels von den Datentypen der Zielspalten abhängen. Spalten, welche einen Fremdschlüssel enthalten, sollten als Typ "reference" definiert werden. In diesem Fall muss die Implementierung den korrekten Datentyp automatisch festlegen.

Die Attribute "ondelete" und "onupdate" definieren, wie das DBMS auf eine Änderung der Referenz reagieren soll.

no-action
Die Referenz in der Kindtabelle darf nicht auf einen Wert gesetzt werden, den keine Zeile in der Elterntabelle entspricht.
restrict
Der Wert eines Schlüssels in der Elterntabelle darf nicht verändert werden, falls noch eine Referenz auf diesen Wert existiert.
cascade
Wenn der Schlüssel in der Elterntabelle gelöscht oder aktualisiert wird, werden alle darauf verweisenden Spalten in der Kindtabelle auch aktualisiert oder gelöscht.
set-null
Wenn der Schlüssel in der Elterntabelle sich ändert, wird der Wert der Referenz auf NULL gesetzt.
set-default
Wenn der Schlüssel in der Elterntabelle sich ändert, wird der Wert der Referenz auf den Default-Wert zurückgesetzt.

Das Attribut "match" definiert, wann das DBMS die referentielle Integrität als erfüllt betrachten soll. Dies betrifft nur zusammengesetzte Fremdschlüssel, welche mehrere Spalten verwenden.

full
Alle Spalten müssen die Bedingung erfüllen.
partial
Mindestens eine Spalte muss die Bedingung erfüllen.
simple
Alle Spalten, die einen Wert haben, müssen die Bedingung erfüllen (manche Spalten können null sein).
Implementierung

Das Attribut "deferrable" wird von einigen DBMS nicht unterstützt. Beachten Sie, dass diese Eigenschaft nicht simuliert werden kann. Verschiedene DBMS haben verschiedene Herangehensweisen, um dieses Problem zu umgehen. Z.Bsp. das vorübergehende Deaktivieren von Constraints. Nähere Informationen finden Sie in Ihrem Handbuch.

Das Attribut "match" wird durch einige DBMS nicht unterstützt. Dies betrifft nur zusammengesetzte Fremdschlüssel, welche mehrere Spalten verwenden. Dieses Feature wird selten verwendet und sollte für Datenbankanwendungen aus Gründen der Kompatibilität vermieden werden.

Einige Werte der Attribute "onupdate" und "ondelete" werden durch einige DBMS nicht unterstützt. Diese können simuliert werden durch die Verwendung von Trigger.

Element Key

  ELEMENT key EMPTY
  ATTRIBUTE
       name           string
       column         string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Name der Spalte in der Quelltabelle.
column string - - Name der Spalte in der Zieltabelle. Der Default-Wert ist der Primärschlüssel der Zieltabelle.
Beschreibung

Eine Referenz einer Quell- auf eine Zielspalte. Wenn ein Fremdschlüssel mehr als eine Referenz definiert, handelt es sich um einen sogenannten "zusammengesetzten" Fremdschlüssel (compound foreign key). Beachten Sie, dass zusammengesetzte Schlüssel sehr kompliziert in der Verarbeitung sind, und nicht von allen DBMS unterstützt werden. Zusammengesetzte Schlüssel sollten wenn möglich vermieden werden.

Element Index

  ELEMENT index (description?, column*)
  ATTRIBUTE
       name           string
       unique         bool
       clustered      bool
       title          string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string - - Ein eindeutiger Name welcher diesen index identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
unique bool - no Ein Unique-Index impliziert stets einen Unique-Constraint. Ein Unique-Constraint bedeutet, dass die Spalte keinen Wert mehrfach enthalten darf.
clustered bool - no Besagt, dass alles Spalten im Tablespace in der Reihenfolge dieses Index gespeichert werden sollen. Das ist eine Einstellung zur Verbesserung der Performance.
title string - - Title ist ein Beschriftungstext, der in der Nutzeroberfläche angezeigt werden sollte wenn das Objekt anzeigt wird.
Beschreibung

Indexes werden verwendet, um die Leistung von Abfragen zu verbessern. Ein Index ist eine sortierte Liste von Spaltenwerten. Das Durchsuchen eines Index ist gewöhnlich schneller als die Suche über eine ganze Tabelle. Jedoch: das Erzeugen und Verwalten eines Indexes erzeugt einen Overhead an Rechenzeit, Insert- und Update-Anweisungen werden daher langsamer wenn Indexe verwendet werden.

Implementierung

Beachten Sie: es ist nicht erforderlich einen Unique-Constraint auf einen Primärschlüssel explizit anzulegen. Primärschlüssel haben bereits implizit einen Unique-Constraint.

Wichtig! Selbst wenn ein Unique-Index besteht, muss die Implementierung nicht unbedingt melden, dass die Spalte einen Unique-Constraint besitzt. Es wird empfohlen Unique-Indexes nicht zu verwenden, wenn das Gleiche mit einem Constraint ausgedrückt werden kann. Beachten Sie, dass ein Unique-Constraint nicht über mehrere Spalten definiert werden kann. In diesem Fall sollten Sie einen Unique-Index verwenden.

Clustered Indexes betreffen ausschließlich MSSQL. Ein clustered Index bedeutet, dass der DBS versuchen soll, Werte die im Index nah beieinander liegen auch im Tablespace nah beieinander abzulegen, damit diese beim Lesen der Tabelle in den gleichen Speicherblock passen.
In den meisten Fällen würde erwartet, dass ein clustered Index auf dem Primärschlüssel erzeugt wird (dies ist ohnehin der Standardfall), oder auf einer stattdessen zur Sortierung verwendeten Spalte. Pro Tabelle darf nur ein clustered Index angelegt werden. Wenn das Attribut clustered eines Index auf "yes" gesetzt wird, dann muss die Implementierung prüfen, ob in der Tabelle bereits ein anderer clustered Index definiert ist. Falls dies der Fall ist, so muss das Attribut clustered dieses Index auf "no" gesetzt werden. Die Implementierung kann einen Fehler melden, wenn zwei clustered Indexes in einer Tabelle gefunden werden.

Element Column

  ELEMENT column EMPTY
  ATTRIBUTE
       name           string
       sorting        string
       length         string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Name der indexierten Spalte in der Quelltabelle.
sorting string - ascending In einem Index kann zum Zweck der Optimierung jede Spalte getrennt auf- oder absteigend sortiert werden. Das wird insbesondere für Indexe über mehrere Spalten verwendet.
ascending
Sortierung erfolgt in aufsteigender Reihenfolge
descending
Sortierung erfolgt in absteigender Reihenfolge
length integer - - maximale Länge der im Index gespeicherten Werte
Beschreibung

Die Liste der in einem Index hinterlegten Spalten gibt an, welche Spalten einer Tabelle in den Index aufgenommen, und wie diese Werte gespeichert werden.

Implementierung

Das Attribut length dient der Optimierung der Performance und wird nur in MySQL verwendet. Andere DBMS unterstützen dieses Argument nicht. Beachten Sie, dass das Attribut length nicht größer sein darf als die Länge der Quellspalte.
Die Implementierung kann automatisch entscheiden, ob ein Volltextindex angelegt werden soll, falls das DBMS dieses Feature unterstützt.

Views

Grundsätzlich werden über "Views" Select-Abfragen abgebildet. Daher können diese mehrere Tabellen einbeziehen, Daten aggregieren oder Informationen ausblenden. Für den Nutzer können sie sich wie echte Tabellen verhalten. Views werden weitgehend für Formulare und Benutzerschnittstellen verwendet.
Jedoch sollten Sie beachten, dass es einige Beschränkungen gibt. Wenn Sie Daten in einem View ändern wollen, muss der View aktualisierbar (updatable) sein. Die Unterstützung dieses Features hängt vom gewählten DBMS ab. Manche Hersteller beschränken dies auf bestimmte (sehr einfache) Szenarien. Einfacher gesagt, ein "updatable View" muss den Primärschlüssel und die Quelltabelle für alle Spalten des Views wissen. Die Where-Klausel der Abfrage spezifiziert eine Art Constraint eines Views und kann fordern, dass jede aktualisierte oder eingefügte Spalte diesem Constraint entspricht und somit wieder im View enthalten ist.

Element View

  ELEMENT view (description?, grant*, field+, select*)>
  ATTRIBUTE
       name        string
       readonly    bool
       tables      string
       where       string
       orderby     string
       sorting     string
       checkoption string
       title       string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher diesen View identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
readonly boole - no Sie können den View auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Ein View, welcher schreibgeschützt ist, kann nicht aktualisiert werden (ist nicht updatable).
tables nmtokens - - Eine durch Kommata getrennte Liste von Tabellen, welche im aktuellen View verwendet werden. Wenn die Liste mehr als eine Tabelle enthält, so ist die erste die Basistabelle, und alle weiteren Tabellen werden mit dieser über einen Join verknüpft.
Vergessen Sie nicht eine Where-Klausel für die verknüpften Tabellen zu definieren.
where string - - Das ist eine generische Information. Sie setzt die Where-Klausel des Views.
orderby string - - Eine durch Kommata getrennte Liste von Spalten, nach denen die Ausgabe sortiert wird. Standardmäßig wird nach dem Primärschlüssel der Tabelle sortiert.
sorting string - ascending
ascending
Sortierung erfolgt in aufsteigender Reihenfolge
descending
Sortierung erfolgt in absteigender Reihenfolge
checkoption string - none
none
keine Prüfung
cascaded
rekursive Prüfung
local
nur lokale Prüfung
title string - - Title ist ein Beschriftungstext, der in der Nutzeroberfläche angezeigt werden sollte wenn das Objekt anzeigt wird.
Beschreibung

Das "View"-Element definiert den Namen, die Dokumentation und allgemeine Eigenschaften eines Datenbank-Views. Dies sind seine Basistabellen, Where-Klausel und andere Informationen, welche es einer Anwendung erlauben sollen, die Elemente des Views einer echten Tabelle zuzuordnen. Dies sollte es einer Implementierung ermöglichen, einfache und updatable Views für solche DBMS zu simulieren, welche dieses Feature nicht unterstützen. Eine Implementierung kann die Simulation von Views mit Hilfe der generischen Informationen unterstützen. Die Implementierung kann einen Fehler melden, falls es ihr nicht möglich ist einen View zu simulieren und das DBMS das geforderte Feature nicht unterstützt.

Implementierung

Die Implementierung muss einen View als "updatable" (aktualisierbar) betrachten, sofern das Attribut "readonly" nicht auf "yes" gesetzt ist. Sie kann jedoch entscheiden, dass ein View keine Änderungen erlaubt, wenn ein erforderlicher Primärschlüssel fehlt. Wo dies möglich ist kann die Implementierung automatisch einen Primärschlüssel zur generischen Abfrage hinzunehmen, um den View updatable zu machen. Für DBMS, welche updatable Views nicht unterstützen, kann die Implementierung diese simulieren, indem sie Insert- oder Update-Anweisungen basierend auf den gegebenen generischen Informationen selbst erzeugt. Die Implementierung kann einen Fehler melden, wenn der Nutzer versucht einen View für ein betroffenes DBMS zu ändern und sie nicht in der Lage ist, das gewünschte Verhalten zu simulieren.

Das Attribut "where" definiert die Where-Klausel des Views. Diese Information muss bei der Simulation des Views beachtet werden. Eine Implementierung kann die korrekte Syntax für dieses Element selbst definieren. Beachten Sie! Folgende Schreibweise wird nicht empfohlen "time < now()" weil die Funktion "now()" zwischen verschiedenen DBMS nicht kompatibel ist. Sie können jedoch zusätzlich abweichende SQL-Abfragen für ein bestimmtes Ziel-DBMS Ihrer Wahl definieren. Die vom Yana Framework unterstützte Syntax für generische Where-Klauseln ist: {[column]=[value]{ AND [column]=[value]}*}.

Das Attribut "checkoption" steuert die Auswertung der Where-Klausel. Der Unterschied zwischen 'local' und 'cascaded' betrifft nur Situationen, in denen ein View rekursiv auf einem anderen View aufgebaut wird und der Elternview selbst einen Constraint (Check-Option) definiert. In diesem Fall hindert die Einstellung 'local' den DBS daran, die Check-Option(en) des Elternviews rekursiv zu prüfen. Beachten Sie, dass diese Einstellung nicht von allen DBMS unterstützt wird.
Z.Bsp. wird von MySQL und PostgreSQL dieses Feature unterstützt , während MSSQL keine Unterstützung bietet.

Element Select

  ELEMENT select (#PCDATA)
  ATTRIBUTE
       dbms     string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
dbms string - generic Der Name des Ziel-DBMS. Der Wert "generic" bedeutet, dass die Definition für jedes DBMS zutreffend ist. Gewöhnlich wird das als Rückfalloption für DBMS verwendet, an welche Sie entweder beim Erstellen der Datenbankstruktur noch nicht gedacht haben, oder welche das fragliche Feature nicht unterstützen.
Beschreibung

Das "select" Element ist eine DBMS-abhängige SQL-Anweisung. Diese muss den definierten Namen der Basistabellen, Spalten und anderen View-Eigenschaften entsprechen. Für einfache Views kann die generische Information bereits ausreichend sein, so dass keine zusätzlichen Select-Elemente angegeben werden müssen. Daher sollte das Select-Element falls möglich vermieden werden.

Element Field

  ELEMENT field EMPTY
  ATTRIBUTE
       table        string
       column       string
       alias        string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
table string - - Name der Basistabelle
column string - - Name der Basisspalte
alias string - - optionaler Alias
Beschreibung

Eine Spaltenreferenz, welche den Namen einer Spalte im View (siehe Attribut "alias") dem Namen der physischen Tabelle und Spalte zuordnet, auf welcher diese basiert.

Formulare

Dieser Abschnitt definiert die Syntax von Elementen die erforderlich sind, um die Struktur von Formularen zu definieren, welche an Objekte in der Datenbank gebunden sind. Diese Formulare können durch eine Client-Anwendung verwendet werden und beziehen sich auf Datenbankelemente, welche innerhalb des gleichen Dokuments definiert wurden. Formulare binden eine Darstellung (Template) an eine Datenquelle (Tabelle oder View). Die Implementierung kann die erforderliche Syntax und Interpretation der Templates selbst festlegen. Diese Aspekte sind in diesem Dokument nicht spezifiziert.

Element Form

  ELEMENT form (description?, grant*, input*, form*, event*)
  ATTRIBUTE
       name        string
       table       string
       template    string
       key         string
       allinput    bool
       title       string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher dieses Formular identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
name string ja - Ein eindeutiger Name welcher dieses Formular identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
table string - - Name einer Quelltabelle oder eines Views. Beachten Sie, dass der View updatable sein sollte. Andernfalls sollte das Formular nicht editierbar sein.
template string - - Das Attribut template kann einen beliebigen Text enthalten. Die Implementierung zur Generierung des Formulars kann eine Liste gültiger Werte für dieses Attribut festlegen. Das Template sollte alle erforderlichen Informationen liefern, welche die Implementierung zur Darstellung des Formulars benötigt.
key string - - Für jedes eingebettete Subformular gilt, dass dessen Basistabelle über einen Fremdschlüssel direkt mit der Basistabelle des Elternformulars verbunden sein muss. Sollte es mehrere passende Fremdschlüssel geben, so kann das Attribut key angeben, über welchen Fremdschlüssel die Tabellen verknüpft werden sollen. Fehlt das Attribut key, so muss die Implementierung den ersten passenden Fremdschlüssel verwenden. Die Implementierung kann einen Fehler melden, falls kein passender Fremdschlüssel existiert, oder das Attribut key auf einen ungültigen Fremdschlüssel verweist.
allinput bool - no Das Attribut allinput gibt an, ob beim Erzeugen des Formulars automatisch nicht definierte Spalten der Basistabelle in das Formular übernommen werden sollen. Dies dient dazu redundante Angaben zu vermeiden. Hat dieses Attribut den Wert "yes", so muss die Implementierung für alle fehlenden Tabellenspalten im Formular Input-Elemente mit der Default-Belegung erstellen. Die Namen der Elemente müssen den Spaltennamen entsprechen.
title string - - Title ist ein Beschriftungstext, der in der Nutzeroberfläche angezeigt werden sollte wenn das Objekt anzeigt wird.
Beschreibung

Formulare sind benannte Objekte, welche als Eingabe für Formular- und Oberflächengeneratoren benutzt werden. Sie müssen mindestens eine Basistabelle und ein Template festlegen. Die Basistabelle darf natürlich auch ein (updatable) View sein.

Implementierung

Formulare sind kein Feature der Datenbank. Sie müssen für alle bekannten DBMS durch Software generiert werden. Der Inhalt des Formulars basiert jedoch auf dem Datenbankschema, welches in der XDDL-Datei definiert ist. Basierend auf diesen Informationen sollte die Implementierung Select-, Update-, Insert- oder Delete-Anweisungen selbstständig generieren.

Darstellung

In einer Ausgabe als HTML, sollten Formulare als Form-Elemente angezeigt werden. Die Darstellung des Formulars muss im mit dem Form-Element verbundenen Template definiert sein.

Formulare dürfen verschachtelt sein und Subformulare enthalten, deren Elemente aus der gleichen, oder anderen Tabellen stammen können. Eingebettete Subformulare können kurch Verwendung des Tags "fieldset" dargestellt werden. Das Attribut title kann als Wert für ein "legend"-Element des Tags verwendet werden.

Element Input

  ELEMENT input (description?, grant*, event*)

  oder, falls das Input-Element sich auf keine Tabellenspalte in der Datenbank beziehen soll:

  ELEMENT input ( (array | bool | color | date | enum | file | float |
                html | image | inet | integer | list | mail | password |
                range | reference | set | string | text | time |timestamp |
                url), event*)
  ATTRIBUTE
       name        string
       label       string
       hidden      bool
       readonly    bool
       cssclass    string
       tabindex    integer
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher das Formularfeld identifiziert. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
label string - - Das Attribut label ist ein Beschriftung welche Informationen zum Inhalt des Formularfelds liefert.
hidden bool - no Das Formularfeld darf in der Nutzeroberfläche nicht sichtbar sein, wenn der Wert dieses Attributs auf "yes" gesetzt wird. Andernfalls soll das Attribut ignoriert werden.
readonly bool - no Sie können das Formularfeld auf schreibgeschützt setzen, um zu verhindern dass Änderungen vorgenommen werden. Ein Formularfeld, welches schreibgeschützt ist, kann nicht editiert werden.
cssclass string - - Eine HTML-basierte Nutzeroberfläche sollte Id-Attribute und CSS-Klassen für Formularfelder automatisch bereitstellen. Zusätzlich kann dieses Attribut verwendet werden um eine nutzerdefinierte CSS-Klasse hinzuzufügen.
tabindex integer - 0 Eine HTML-basierte Nutzeroberfläche sollte den Tab-Index für Formularfelder automatisch erstellen. Alternativ kann dieses Attribut verwendet werden um einen nutzerdefinierten Wert festzulegen. Der Tab-Index definiert die Reihenfolge, in welcher Formularfelder den Eingabefokus erhalten, wenn der Nutzer die Tabulatortaste des Keyboards drückt.
Beschreibung

Das Input-Element bezeichnet ein einzelnes Formularfeld.

Wenn sich dabei auf ein echtes Feld in der Datenbank bezogen wird, so bezeichnet das Attribut "name" den Namen der Spalte. Andernfalls muss die Spalte innerhalb des Elements direkt deklariert werden.

Darstellung

Eine HTML-basierte Nutzeroberfläche sollte dies darstellen als "input"-Element oder etwas vergleichbares, abhängig vom Typ der zugrundeliegenden Spalte. Wenn das Attribute "readonly" auf "yes" gesetzt ist, sollte das Element nicht editierbar sein. Die Implementierung sollte CSS Class- und/oder Id-Attribute für jedes Formularfeld automatisch erzeugen. Zusätzlich muss, wenn das Attribut "cssclass" gesetzt wird, dieser Wert zum Attribut Class des Tags hinzugefügt werden. Wenn das Attribut "tabindex" angegeben ist, muss es in die Attributliste des Steuerelements kopiert werden. Falls das "input"-Element durch mehr als ein HTML-Element umgesetzt wird, so muss das Attribut tabindex auf das erste editierbare Feld gesetzt werden.

Element Event

  ELEMENT event (#PCDATA)
  ATTRIBUTE
       name     string
       language string
       title    string
       label    string
       icon     image
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Ein eindeutiger Name welcher das Ereignis identifiziert. Sollte kleingeschrieben und ein gültiger Funktionsname sein.
language string - - Die Programmiersprache in welcher die Ereignisbehandlung implementiert ist. Kann eine beliebige Zeichenkette sein. Falls diese Option nicht angegeben ist, kann die Implementierung selbst festlegen, wie das Ereignis zu behandeln ist. Das Yana Framework wird den Bereich PCDATA in diesem Fall als Namen einer statischen Methode in PHP interpretieren, welche die Ereignisbehandlung implementiert.
title string - - Attribut title zur Verwendung in anklickbaren Links.
label string - - Beschriftung von anklickbaren Links.
icon image - - Grafikdatei zur Verwendung als Icon für anklickbare Links.
Beschreibung

Das Ereignis wird ausgelöst, wenn der Benutzer im angezeigten Formular eine bestimmte Aktion auslöst, wie das Absenden des Formulars, das Anklicken eines Downloads, oder was vergleichbares. Die verfügbaren Typen von Ereignissen müssen durch das gewählte Template definiert werden. Die Implementierung kann selbst definieren, wie das Ereignis ausgewertet werden soll. Das Attribut "name" definiert den Namen des Ereignisses, und der PCData-Abschnitt den Namen der aufzurufenden Funktion.

Beispiel: Ereignis "submit" mit PCData "foo" wird die Formulardaten über die Methode POST zur Server-Anwendung mit der URL "?action=foo" senden, wenn der Benutzer das Formular absendet (den "submit" Button betätigt). Die Implementierung muss definieren, was "submit" für im Falle des angegebenen Formulartemplates tatsächlich bedeutet.

Darstellung

Die Darstellung des Elements hängt von den Attributen language und name ab.

Für die Sprache PHP, oder wenn das Attribut language leer ist, wird empfohlen zur Darstellung einen "A"-Tag neben dem Formularfeld zu verwenden. Der Inhalt des HTML-Tags besteht aus dem Attribut label und/oder einem Image-Tag, dessen Attribut "src" aus dem Attribut "icon" übernommen wird. Das Attribute "href" des HTML-Tags sollte eine Referenz auf PHP_SELF und den Namen der Aktion als Parameter beinhalten, in der Form "action={name}". Als Wert des Feldes sollte als zweiter Parameter "target[{primärschlüssel}]={wert}" angegeben werden.

Beispiel:

  <action name="foo" label="klick mich"
      icon="common_files/icon.png"/>

  <a href="?action=foo&target[12]=bar">
    klick mich
    <img src="common_files/icon.png"/>
  </a>

Für die Sprache JavaScript, muss das Attribut name eine gültige Bezeichnung für ein Ereignis in JavaScript sein, und der Abschnitt PCDATA muss gültigen JavaScript-Code enthalten.

Beispiel:

  <action name="onchange" language="javascript">validate(this)</action>

  <input ... onchange="validate(this)"/>

Wenn ein "label" oder "icon" angegeben sind, soll die Aktion ausgeführt werden wenn das "label" und/oder "icon" angeklickt worden sind.

Beispiel:

  <action name="onchange" label="prüfen"
      icon="common_files/validate.png"
      language="javascript">validate('foo')</action>

  <input ... onchange="validate('foo')" />
  <a onclick="validate('foo')">
      prüfen
      <img src="common_files/validate.png"/>
  </a>

Die Umsetzung kann alternativ als Button erfolgen.

Beispiel:

  <action name="submit" label="abschicken"
      title="Klick mich!"
      icon="common_files/submit.png"
      language="php">foo</action>

  <button type="submit" title="Klick mich!" name="foo">
      <img src="common_files/submit.png"/>
      abschicken
  </button>

Funktionen

Dieser Abschnitt definiert die Syntax aller Elemente die erforderlich sind um nutzerdefinierte Funktionen zu deklarieren, welche innerhalb des Kontextes der Datenbank verwendet werden sollen. Funktionen bestehen aus der Signaturinformation und dem Funktionsrumpf. Beachten Sie: Während die Signatur der Funktion unter mehreren DBMS kompatibel sein kann, muss dies für die Implementierung nicht zutreffen.

Element Function

  ELEMENT function (description?, implementation+)
  ATTRIBUTE
       name        string
       title       string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Name der Funktion. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
title string - - Title ist ein Beschriftungstext, der in der Dokumentation des Objektes angezeigt werden sollte.
Beschreibung

Eine nutzerdefinierte Funktion mit dem angegebenen Namen. Die Funktion darf maximal eine Implementierung für jedes unterstützte DMBS geben.

Element Implemetation

  ELEMENT implementation (param*, return?, code)
  ATTRIBUTE
       dbms        string
       language    string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
dbms string - generic Der Name des Ziel-DBMS. Der Wert "generic" bedeutet, dass die Definition für jedes DBMS zutreffend ist. Gewöhnlich wird das als Rückfalloption für DBMS verwendet, an welche Sie entweder beim Erstellen der Datenbankstruktur noch nicht gedacht haben, oder welche das fragliche Feature nicht unterstützen.
language string - - Die vorgesehene Programmiersprache. Dies betrifft nur DBMS, welche mehr als eine Sprache unterstützen.
Beschreibung

Die Implementierung definiert die Funktionssignatur und den Quellcode. Die Anzahl der Parameter muss in jedes DBMS (und jedes Implementation-Element) identisch sein.

Implementierung

Falls das Attribut dbms auf "generic" gesetzt ist, kann die XDDL-Implementierung entscheiden, ob die generische Definition der Funktion kompatibel mit einem bestimmten DBMS ist. Falls diese entscheidet, dass die Definition nicht kompatibel ist, kann sie versuchen die Funktion zu simulieren. Für diesen Fall kann die Implementierung die erforderliche Syntax für die Unterelemente "code", "param" und "return" selbst festlegen. Falls die Definition der erforderlichen Syntax nicht entspricht, kann die XDDL-Implementierung einen Fehler melden.

Beachten Sie, dass das Attribut "language" DBMS-abhängig ist. Die meisten DBMS sollten zumindest die Sprache "SQL" unterstützen, während andere auch "Java", "C" oder auch mehr unterstützen können.
Wenn keine Sprache gegeben wird, wird die default Sprache verwendet. Beachten Sie, dass die Implementierung nicht prüfen muss, ob die angegebene Sprache vom angegebenen DBMS unterstützt wird.

Für simulierte Funktionen muss das Attribut language leer sein.

Element Param

  ELEMENT param EMPTY
  ATTRIBUTE
       name     string
       type     string
       mode     string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - eindeutige Parameterbezeichnung
type string ja - DBMS-abhängiger Datentyp
mode string - in Das Attribute "mode" identifiziert das Element als
in
Eingabeparameter (Wertparameter)
out
Ausgabeparameter (Übergabe per Referenz)
inout
Referenzparameter (Übergabe per Referenz)
Beschreibung

Eine Parameterdefinition als ein Teil der Funktionssignatur. Das Attribut "mode" definiert das Verhalten des Parameters. Der Typ des Parameters ist vom DBMS abhängig.

Beispiel:

  <function name="foo">
    <implementation>
      <param name="p1" type="string" mode="in"/>
      <param name="p2" type="float" mode="inout"/>
      <param name="p3" type="int" mode="out"/>
      <return>int</return>
      <code>...</code>
    </implementation>
  </function>

  Kann interpretiert werden als:

  int foo ( string $p1,  float &$p2,  int &$p3 = null ) { ... }
  

Beachten Sie, dass manche DBMS nur Eingabeparameter (Wertparameter) unterstützen. In diesem Fall muss das Attribut mode den Wert "in" haben. Die Implementierung kann einen Fehler melden, wenn eine nicht unterstützte Definition gefunden wird.

Element Return

  ELEMENT return (#PCDATA)
  
Beschreibung

Der durch die Funktion zurückgegebene Datentyp. Diese Einstellung ist DBMS-abhängig.

Wenn kein Rückgabewert definiert, oder die Angabe leer ist, so wird der Defaultwert "void" verwendet, was bedeutet, dass die Funktion keinen Wert zurückgibt. Falls die Funktion mehr als einen Wert zurückgeben muss, sollten stattdessen Ausgabeparameter (mode=out) verwendet werden.
Beachten Sie, dass in MySQL Funktionen, die keinen Rückgabewert haben, "Methoden" genannt werden.

Element Code

  ELEMENT code (#PCDATA)
  
Beschreibung

Der Funktionsrumpf. Die Syntax des Inhaltes hängt von den Parametern für DBMS und Programmiersprache ab. Wenn das DBMS auf "generic" gesetzt ist, dann wird dieser Code durch die Server-Anwendung ausgeführt. Für diesen Fall kann die Implementierung die erforderliche Syntax selbst festlegen. Es wird empfohlen, dass das Element code darauf beschränkt wird, den Namen einer Funktion anzugeben, welche die Implementierung aufrufen kann. Alle Eingabeparameter werden an diese Funktion weitergeleitet. Beachten Sie, dass generische Funktionen innerhalb von SQL-Anweisungen nicht verwendet werden können, weil diese nicht vom DBMS ausgeführt werden.

Aktualisierungen (ChangeLog)

Dieser Abschnitt definiert die Syntax aller Elemente die notwendig sind, um signifikante Änderungen der Datenbank nachzuvollziehen, welche eine Aktualisierung der physischen Datenbankstruktur erfordern. Das schließt kürzlich erstellte, umbenannte, modifizierte und gelöschte Datenbankobjekte ein. Für weitere Aktionen, welche durch diese Definition nicht abgedeckt sind, können SQL-Anweisungen können angegeben wird. Implementierungen können eine Funktion bereitstellen, welche die erforderlichen SQL-Anweisungen generiert, um eine gegebene Datenbank auf eine spätere Version des XDDL-Dokumentes zu aktualisieren. Das ChangeLog sollte jede Information enthalten, die notwendig, ist um solch eine Aktion durchzuführen.

Element Changelog

  ELEMENT changelog (create|rename|drop|update|sql|change)*
  
Beschreibung

Das Element changelog einer Datenbankdefinition wird benutzt, um Änderungen zu dokumentieren. Updates müssen in absteigender Reihenfolge nach ihrer Versionsnummer sortiert sein. Dies bedeutet, dass das erste Element stets der letzten Änderung entspricht.
Die Aktualisierungen enthalten den Typ der Änderung, eine Versionsnummer, und das geänderte Element. Eine Beschreibung der Änderung kann als PCDATA hinzugefügt werden.

Implementierung

Das ChangeLog kann für automatisierte Aktualisierungen der Datenbank verwendet werden. Der Implementierung kann eine Anwendung zur Verfügung stellen, welche das ChangeLog analysiert und das Schema der Datenbank von einer gegebenen Versionsnummer auf eine spätere Version aktualisiert. Diese Implementierung sollte versuchen, alle Änderungen innerhalb einer Transaktion durchzuführen. Im Fall eines nicht behebbaren Fehlers, sollte sie versuchen, sämtliche Änderungen zurückzunehmen.

Element Create

  ELEMENT create (description?)
  ATTRIBUTE
       name        string
       subject     string
       version     string
       ignoreError bool
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Eindeutiger Name des geänderten Objektes. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
subject string ja - table | column | index | view | sequence | trigger | constraint
version string - - Die Version, auf welche sich der Eintrag bezieht.
ignoreError bool - no Wird verwendet, um der Funktion, welche die Aktualisierung durchführt, mittzuteilen, wie diese reagieren soll, falls dieser Schritt während der Aktualisierung der Datenbankstruktur einen Fehler verursacht. Für den Wert "yes" sollte die Aktualisierung der Datenbank fortgesetzt werden, selbst wenn dieser Schritt fehlschlägt. Für den Wert "no" sollte die Aktualisierung gestoppt und alle vorherigen Änderungen zurückgenommen werden.
Beschreibung

Dokumentiert die Erstellung eines neuen Datenbankelements. Der Typ des Elements wird als Attribut "subject" gespeichert. Das Element selbst wird über das Attribut "name" identifiziert. Der Name muss ein eindeutiger Bezeichner des Elements sein. Wo erforderlich muss dieser die Namensräume spezifizieren, innerhalb derer der Name des Elements eindeutig ist. In diesem Fall muss das Zeichen "." als Trennzeichen verwendet werden. Die Implementierung kann einen Fehler melden, wenn das Element nicht gefunden wurde oder nicht eindeutig ist. Das Description-Element kann zu Dokumentationszwecken verwendet werden und beliebigen Text enthalten.

Element Rename

  ELEMENT rename (description?)
  ATTRIBUTE
       name        string
       subject     string
       version     string
       ignoreError bool
       oldname     string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Eindeutiger Name des geänderten Objektes. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
subject string ja - table | column | index | view | sequence | trigger | constraint
version string - - Die Version, auf welche sich der Eintrag bezieht.
ignoreError bool - no Wird verwendet, um der Funktion, welche die Aktualisierung durchführt, mittzuteilen, wie diese reagieren soll, falls dieser Schritt während der Aktualisierung der Datenbankstruktur einen Fehler verursacht. Für den Wert "yes" sollte die Aktualisierung der Datenbank fortgesetzt werden, selbst wenn dieser Schritt fehlschlägt. Für den Wert "no" sollte die Aktualisierung gestoppt und alle vorherigen Änderungen zurückgenommen werden.
oldname string - - Vorheriger Name des umbenannten Objektes. Hinweis: Für Tabellenspalten muss der Name den Namen der Tabelle enthalten ("table.column").
Beschreibung

Dokumentiert die Umbenennung eines existierenden Datenbankelements. Der Typ des Elements wird als Attribut "subject" gespeichert. Das Element selbst wird über das Attribut "name" identifiziert. Der vorherige Name des Elements wird als Attribut "oldname" gespeichert. Der Name muss ein eindeutiger Bezeichner des Elements sein. Wo erforderlich muss dieser die Namensräume spezifizieren, innerhalb derer der Name des Elements eindeutig ist. In diesem Fall muss das Zeichen "." als Trennzeichen verwendet werden. Die Implementierung kann einen Fehler melden, wenn das Element nicht gefunden wurde oder nicht eindeutig ist. Das Description-Element kann zu Dokumentationszwecken verwendet werden und beliebigen Text enthalten.

Element Drop

  ELEMENT drop (description?)
  ATTRIBUTE
       name        string
       subject     string
       version     string
       ignoreError bool
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Eindeutiger Name des geänderten Objektes. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
subject string ja - table | column | index | view | sequence | trigger | constraint
ignoreError bool - no Wird verwendet, um der Funktion, welche die Aktualisierung durchführt, mittzuteilen, wie diese reagieren soll, falls dieser Schritt während der Aktualisierung der Datenbankstruktur einen Fehler verursacht. Für den Wert "yes" sollte die Aktualisierung der Datenbank fortgesetzt werden, selbst wenn dieser Schritt fehlschlägt. Für den Wert "no" sollte die Aktualisierung gestoppt und alle vorherigen Änderungen zurückgenommen werden.
version string - - Die Version, auf welche sich der Eintrag bezieht.
Beschreibung

Dokumentiert die Löschung eines existierenden Datenbankelements. Der Typ des Elements wird als Attribut "subject" gespeichert. Das Element selbst wird über das Attribut "name" identifiziert. Der Name muss ein eindeutiger Bezeichner des Elements sein. Wo erforderlich muss dieser die Namensräume spezifizieren, innerhalb derer der Name des Elements eindeutig ist. In diesem Fall muss das Zeichen "." als Trennzeichen verwendet werden. Die Implementierung kann einen Fehler melden, wenn das Element nicht gefunden wurde oder nicht eindeutig ist. Das Description-Element kann zu Dokumentationszwecken verwendet werden und beliebigen Text enthalten.

Eine typische Situation, in welcher das Attribut "ignoreError" mit dem Wert "yes" üblicherweise verwendet wird ist die Löschung eines Elements. Gewöhnlich soll eine Datenbankaktualisierung nicht fehlschlagen, wenn ein Element nicht gelöscht werden kann, weil es nicht (mehr) existiert.

Beachten Sie, dass einige DBMS außer Stande sind, gelöschte Datenbankelemente wiederherzustellen. Im Fehlerfall kann diese Einschränkung Auswirkungen auf das Verhalten der Implementierung haben, welche die Datenbankstruktur aktualisiert.

Element Update

  ELEMENT update (description?)
  ATTRIBUTE
       name        string
       subject     string
       version     string
       ignoreError bool
       property    string
       value       string
       oldvalue    string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string ja - Eindeutiger Name des geänderten Objektes. Sollte kleingeschrieben und ein valider XML-, SQL-Bezeichner sein.
subject string ja - table | column | index | view | sequence | trigger | constraint
version string - - Die Version, auf welche sich der Eintrag bezieht.
ignoreError bool - no Wird verwendet, um der Funktion, welche die Aktualisierung durchführt, mittzuteilen, wie diese reagieren soll, falls dieser Schritt während der Aktualisierung der Datenbankstruktur einen Fehler verursacht. Für den Wert "yes" sollte die Aktualisierung der Datenbank fortgesetzt werden, selbst wenn dieser Schritt fehlschlägt. Für den Wert "no" sollte die Aktualisierung gestoppt und alle vorherigen Änderungen zurückgenommen werden.
property string - - Gibt an welche Eigenschaft des Objektes aktualisiert worden ist.
value string - - Der neue Wert der Eigenschaft, welche aktualisiert wird. Die Syntax dieses Attributs kann durch die Implementierung festgelegt werden. Der Wert kann ein serialisierter Text sein.
oldvalue string - - Der alte Wert der geänderten Eigenschaft. Die Syntax dieses Attributs kann durch die Implementierung festgelegt werden. Der Wert kann ein serialisierter Text sein.
Beschreibung

Dokumentiert die Änderung eines existierenden Datenbankelements. Der Typ des Elements wird als Attribut "subject" gespeichert. Das Element selbst wird über das Attribut "name" identifiziert. Der Name muss ein eindeutiger Bezeichner des Elements sein. Wo erforderlich muss dieser die Namensräume spezifizieren, innerhalb derer der Name des Elements eindeutig ist. In diesem Fall muss das Zeichen "." als Trennzeichen verwendet werden. Die Implementierung kann einen Fehler melden, wenn das Element nicht gefunden wurde oder nicht eindeutig ist. Das Description-Element kann zu Dokumentationszwecken verwendet werden und beliebigen Text enthalten. Wo verfügbar kann die geänderte Eigenschaft (property), sowie deren alter (oldvalue) und neuer Wert (value) angegeben werden.

Element Sql

  ELEMENT sql (description?, code)
  ATTRIBUTE
       version     string
       ignoreError bool
       dbms        string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
dbms string - generic Der Name des Ziel-DBMS. Der Wert "generic" bedeutet, dass die Definition für jedes DBMS zutreffend ist. Gewöhnlich wird das als Rückfalloption für DBMS verwendet, an welche Sie entweder beim Erstellen der Datenbankstruktur noch nicht gedacht haben, oder welche das fragliche Feature nicht unterstützen.
version string - - Die Version, auf welche sich der Eintrag bezieht.
ignoreError bool - no Wird verwendet, um der Funktion, welche die Aktualisierung durchführt, mittzuteilen, wie diese reagieren soll, falls dieser Schritt während der Aktualisierung der Datenbankstruktur einen Fehler verursacht. Für den Wert "yes" sollte die Aktualisierung der Datenbank fortgesetzt werden, selbst wenn dieser Schritt fehlschlägt. Für den Wert "no" sollte die Aktualisierung gestoppt und alle vorherigen Änderungen zurückgenommen werden.
Beschreibung

Dokumentiert eine nutzerdefinierte SQL-Anweisung, welche ausgeführt werden soll. Die Ausführung kann auf einen bestimmten DBMS beschränkt werden. SQL-Anweisungen können für jegliche weiteren Aktionen verwendet werden, welche durch andere Elemente dieser Definition nicht abgedeckt sind. Z.Bsp. um Daten in eine kürzlich erstellte Tabelle zu kopieren. Das Description-Element kann zu Dokumentationszwecken verwendet werden und beliebigen Text enthalten. Das Code-Element muss den SQL-Code enthalten.

Element Code

  ELEMENT code (#PCDATA)
  
Beschreibung

Enthält den auszuführenden SQL-Code. Die Syntax des Inhaltes hängt vom Parameter DBMS ab.

Element Change

  ELEMENT change (description?, logparam*)
  ATTRIBUTE
       version     string
       ignoreError bool
       type        string
       dbms        string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
version string - - Die Version, auf welche sich der Eintrag bezieht.
ignoreError bool - no Wird verwendet, um der Funktion, welche die Aktualisierung durchführt, mittzuteilen, wie diese reagieren soll, falls dieser Schritt während der Aktualisierung der Datenbankstruktur einen Fehler verursacht. Für den Wert "yes" sollte die Aktualisierung der Datenbank fortgesetzt werden, selbst wenn dieser Schritt fehlschlägt. Für den Wert "no" sollte die Aktualisierung gestoppt und alle vorherigen Änderungen zurückgenommen werden.
dbms string - generic Der Name des Ziel-DBMS. Der Wert "generic" bedeutet, dass die Definition für jedes DBMS zutreffend ist. Gewöhnlich wird das als Rückfalloption für DBMS verwendet, an welche Sie entweder beim Erstellen der Datenbankstruktur noch nicht gedacht haben, oder welche das fragliche Feature nicht unterstützen.
type string - default Ein beliebiger Text, welcher den Typ der Änderung eindeutig identifiziert.
Beschreibung

Dies ist ein generisches Element zum Ergänzen von nutzerdefinierten Typen von Aktualisierungen. Eine Implementierung zur Ausführung dieses Updates muss es erlauben, für jeden angegebenen Typ eine Funktion oder Methode zu definieren, welche das Element behandelt. Dieser Funktion oder Methode müssen die LogParam-Elemente als Parameter übergeben werden, in der Reihenfolge ihrer Definition. Die Ausführung kann auf einen bestimmten DBMS beschränkt werden. Das Description-Element kann zu Dokumentationszwecken verwendet werden und beliebigen Text enthalten.

Element Logparam

  ELEMENT logparam (#PCDATA)
  ATTRIBUTE
       name     string
  
Attribute
Attribut Typ Pflicht Default Beschreibung
name string - - Name des Parameters
Beschreibung

Ein Parameter, welcher an die aufgerufene Funktion übergeben wird. Der PCDATA-Bereich enthält den Wert des Parameters. Optional kann ein Name vergeben werden. Es dürfen keine zwei Parameter mit dem gleichen Namen definiert werden.

Das SML Dateiformat

Die Bezeichnung "SML" ist eine Abkürzung für "Simple Markup Language". Das SML-Format wurde zwischen 2001 und 2003 mit dem Ziel entwickelt, eine leicht verständliche und syntaktisch saubere Darstellung zu schaffen, welches von einer breiten Masse der Nutzer akzeptiert werden würde.

SML ist gleichermaßen verwandt mit "JSON" ("JavaScript Object Notation") und "XML" ("Extensible Markup Language"). Es ist semantisch gleich mächtig zu JSON. Dies heißt, alle Konstrukte, welche in JSON ausgedrückt werden können, können ebenso im SML-Format dargestellt werden und umgekehrt. Es ist dennoch wichtig zu betonen, dass SML unabhängig von JSON entwickelt wurde. Beide Dialekte haben keinerlei gemeinsame historische Schnittpunkte.

Vereinfacht ausgedrückt, verwendet SML eine Semantik, vergleichbar mit der von JSON und eine Syntax vergleichbar mit der von XML. Es verbindet somit die unter Nutzern weithin akzeptierte Tag-Darstellung mit einer intuitiven Semantik.

Zweck des SML-Formats

Aufgabe des Dateiformats ist es, nicht-rekursive Datenfelder in Form einer sequentiellen Datei zu repräsentieren. Diese Datenfelder können entweder numerisch oder assoziativ sein und beliebige skalare Werte, oder wiederum andere Datenfelder enthalten, welchen den gleichen Anforderungen genügen müssen. Referenzen sind nicht zugelassen. Objekte werden analog zu JSON dargestellt, indem ihre öffentlichen Objektvariablen in Form eines assoziativen Datenfeldes gespeichert werden. Enthaltene nicht skalare Werte werden rekursiv behandelt.

Zweck dieses Dateiformats ist es, Parameter zu speichern, um Komponenten des Frameworks zu initialisieren. Zweck ist es nicht, größere Datenmengen in diesem Format zu speichern. Insbesondere ist das SML-Format nicht konzipiert als Ersatz für XML.

Unendliche Rekursionen werden nicht erkannt.

Diskussion zu Erkennung unendlicher Rekursionen

Zur Begründung ist Folgendes zu sagen: Der Test, ob eine beliebige Struktur unendliche Rekursionen aufweist ist nicht trivial. Der übliche Ansatz ist eine Pfadprüfung. Dabei fällt jedoch jeweils ein Overhead von T = O(n) Schritten an, wobei n der Länge des Pfades entspricht. Der Beweis dieser unteren Schranke für die Laufzeit ist trivial. Um Overhead zu vermeiden könnte in Betracht gezogen werden, diese Prüfung nur alle x Verarbeitungsschritte durchzuführen, wobei für die positive, ganze Zahl x mit x > 1 ein geeigneter Wert gewählt werden sollte. Trotz dieser potentiellen Optimierung ist damit zu rechnen, dass sich für das gesamte Programm inklusive Pfadprüfung eine quadratische Laufzeit ergibt. Dies ist in für viele Anwendungen jedoch nicht akzeptabel. Aus Gründen der Performance wurde daher absichtlich darauf verzichtet.

An dieser Stelle möchte ich anmerken, dass der naive Ansatz, die Zahl der Elemente zu bestimmen und zu prüfen, ob die Zahl der Iterationen die Zahl der Elemente übersteigt, selbstverständlich nicht praktikabel ist. Um alle Elemente zu "zählen", müsste eine vollständige Traversion durchgeführt werden. Falls diese jedoch einen unendlich rekursiven Pfad enthalten sollte, so würde das Programm niemals terminieren und das Ergebnis wäre somit undefiniert.

Von XML zu SML

Die Aufgabe Dateien für die Initialisierung, beziehungsweise Konfiguration eines Frameworks bereitzustellen, ist nicht ganz trivial. Weil das Framework eine Vielzahl von Plugins besitzen kann, deren Konfigurationsoptionen in den gleichen Dateien abgelegt werden sollen wie die restliche Konfiguration. Anzahl, Struktur, Typ und Benennung dieser Daten ist zur Entwurfszeit jedoch unbekannt. Eventuell sind die Plugins, mit denen das Framework arbeiten wird, zu diesem Zeitpunkt auch noch gar nicht geschrieben. Um unter diesen Umständen überhaupt im Voraus eine sinnvolle DTD oder Schema angeben zu können, ist es nur logisch sich auf natürliche Eigenschaften der Variablen zurückzuziehen. Stabile Eigenschaften wie beispielsweise der Datentyp einer Variablen sind geeignet um eine Struktur abzuleiten, welche vorhersagbar ist, weil sie durch stabile syntaktische Eigenschaften von PHP diktiert werden.

Weil PHP nicht streng typisiert ist und Referenzen, sowie Objekte per Definition kein Teil dieser Konfiguration sein dürfen, bleiben die Menge der skalaren Variablen und die Menge der Datenfelder. Dementsprechend werden analog zwei verschiedene Arten von Knoten definiert. Für die Darstellung skalarer Variablen soll der Tag "scalar" eingeführt werden. Dieser darf lediglich CDATA-Abschnitte enthalten – was gerade einem skalaren Kontext entspricht – jedoch keine weiteren Tags, respektive Elemente. Für die Darstellung von Datenfeldern soll der Tag "array" eingeführt werden. Dieser darf wiederum keine CDATA-Bereiche enthalten, sondern lediglich weitere Tags. Diese Tags repräsentieren die Elemente des Datenfelds. Weil XML ein eindeutiges Wurzelelement verlangt, wird zudem der Tag "root" eingeführt. Weitere Tags werden nicht benötigt.

Betrachten Sie das folgende Beispiel, welches zwei Datenfelder darstellt.

<?xml version="1.0" ?>
<!DOCTYPE example SYSTEM "example.dtd">
<root>
	<array name="a">
		<array name="0">
			<scalar name="a"><![CDATA[wert]]></scalar>
			<scalar name="b"><![CDATA[wert]]></scalar>
			<scalar name="c"><![CDATA[wert]]></scalar>
		</array>
		<array name="1">
			<scalar name="a"><![CDATA[wert]]></scalar>
			<scalar name="c"><![CDATA[wert]]></scalar>
		</array>
	</array>
	<array name="b">
		<array name="0">
			<scalar name="q"><![CDATA[wert]]></scalar>
			<scalar name="r" />
			<scalar name="s"><![CDATA[wert]]></scalar>
			<scalar name="t"><![CDATA[wert]]></scalar>
		</array>
	</array>
</root>

An diesem Beispiel fallen einige Besonderheiten auf. Erstens ist das Element "root" völlig ohne semantische Bedeutung. Es existiert einzig und allein, weil die Syntax es erfordert.

Etwas künstlich wirken auch die leeren Tags. Sie sind zwar enthalten, aber es ist nicht ganz klar, wie diese in Bezug auf Variablen interpretiert werden sollen. PHP erfordert keine Definition von Variablen vor der ersten Verwendung. Eine Initialisierung einer zuvor nicht existierenden Variable, geschweige einer Konstante, mit "null" ist somit nicht wirklich sinnvoll. Zumal in einer Konfigurationsdatei ein null-Wert semantisch keinen Sinn machen wird. Daher soll per Konvention festgelegt werden, dass auf leere Tags komplett verzichtet werden sollte. Zugriffe auf leere oder nicht existierende Tags werden gemäß der in PHP üblichen Konventionen zu boolean "false" ausgewertet.

Weiterhin ist absehbar, dass diese Darstellung bei größeren Datenmengen unübersichtlich werden könnte. Betrachtet man beispielsweise den Fall, dass ein Datenfeld möglicherweise 50 oder mehr Einträge aufweist, welche zudem eventuell noch tief verschachtelt sind und große CDATA-Abschnitte mit mehreren Zeilenumbrüchen enthalten, dann ist anzunehmen, dass die Lesbarkeit beeinträchtigt wäre. Es wäre für die Lesbarkeit also von Vorteil, wenn aus einem End-Tag direkt ablesbar wäre, welches Element denn nun gerade geschlossen wurde.

Die gesonderte Kennzeichnung der CDATA-Abschnitte, könnte ebenfalls die Lesbarkeit beeinträchtigen, zumal sich der Sinn für den XML-unerfahrenen Laien nicht trivial erschließen muss. Zudem verlangen die zuvor getroffenen Festlegungen explizit, dass an dieser Position ohnehin gar nichts anderes als ein CDATA-Abschnitt folgen darf, weshalb eine Auszeichnung keinen echten Mehrwert bringt, sondern wiederum lediglich eine syntaktische Ursache hat. Es gibt einen seltenen Ausnahmefall, nämlich dass der CDATA-Abschnitt einen schließenden "scalar"-Tag enthält. Diese Fall kann jedoch auch mit Hilfe von Entities umgangen werden, sodass die Kennzeichnung insgesamt obsolete ist.

Abschließend soll die Schreibweise der Tags betrachtet werden. Beispielsweise die Bezeichnung "<array name="b">". Diese Schreibweise könnte auf Laien, überfrachtet und unnötig kompliziert wirken. Denn: dass es sich um ein Datenfeld handeln muss, wird bereits aus der Struktur des Elements deutlich, weil es nur ein einziges anderes Element gibt. Der Tag "scalar" kann aber aus rein syntaktischen Gründen an dieser Stelle gar nicht stehen, weil dieser keine Tags, sondern nur CDATA enthalten darf. Extra zu erwähnen, dass es sich um ein Datenfeld handelt ist somit im Grunde überflüssig. Das Attribut "name" ist allen Tags gemeinsam. Dies ergibt sich zwangsläufig aus syntaktischen Eigenschaften von PHP. Das Attribut entspricht also dem Bezeichner der Variable in PHP. Intuitiver wäre es statt er Bezeichnung "array" oder "scalar" den Bezeichner der Variablen als Tag zu benutzen. Analog gilt die gleiche Betrachtung für den Tag "scalar".

Berücksichtigt man alle diese Einwände so lässt sich folgende vereinfachte Darstellung gewinnen.

<a>
	<0>
		<a>wert</a>
		<b>wert</b>
		<c>wert</c>
	</0>
	<1>
		<a>wert</a>
		<c>wert</c>
	</1>
</a>
<b>
	<0>
		<q>wert</q>
		<s>wert</s>
		<t>wert</t>
	</0>
</b>

Auch ohne umfangreiche Erläuterung ist erkennbar, dass beide Varianten inhaltlich das Gleiche ausdrücken. Ebenso sollte vermutlich keine Diskussion darüber erforderlich sein, welche der beiden Schreibweisen intuitiver erfassbar, oder leichter lesbar wäre.

Aufgrund ihrer syntaktischen Eigenschaften ist diese Variante jedoch kein wohlgeformtes XML-Dokument mehr. Beispielsweise gibt es mehr als ein Wurzelelement und zudem ist "0" in XML kein gültiger Name für einen Tag. Es war somit notwendig eine andere Bezeichnung zu wählen. Diese Bezeichnung ist "SML" für "simple markup language", in Anlehnung an "XML" ("eXtensible markup language").

Syntaktische Eigenschaften

Gegenüber XML verlangt SML eine Reihe abweichender syntaktischer Eigenschaften. Zunächst ist zu erwähnen, dass die Kodierung einer Datei in UTF-8 oder UTF-16, wie beispielsweise bei XML üblich, leider in vielen Sprachen nach wie vor noch zu Problemen beim Lesen der Dateien führen kann. Zu diesen Sprachen zählen zum gegenwärtigen Zeitpunkt unter anderem Perl 5 und bedauerlicherweise PHP 4. Dies ist zwar ein Versäumnis der Entwickler und keine Eigenschaft von XML als solches, dennoch stellt es einen inakzeptablen Zustand dar, wenn es darum geht eine Anwendung zu initialisieren. Daher ist es sinnvoll für die Zwecke der Initialisierung des Frameworks von der Verwendung dieser Kodierungen abzusehen. Als Zeichensatz wird ISO Latin-1 verwendet. Zeichen, welche darin nicht enthalten sind, sollten durch geeignete Entitäten kodiert werden.

Abweichend von der XML-Syntax wird für SML nicht gefordert, dass das Dokument nur einen einzigen Tags als Wurzelelement enthalten darf. Sollte ein Dokument einen Wald aus mehreren Bäumen enthalten, so werden diese implizit als Kindelemente eines anonymen, virtuellen Wurzelelements enthalten.

Als weitere syntaktische Eigenschaft fordert das SML-Format, dass alle öffnenden Tags durch einen in gleicher Weise benannten schließenden Tag geschlossen werden müssen. Bei der Benennung der Tags kommt es nicht auf die Schreibweise an. Es wird nicht zwischen Groß- und Kleinschreibung unterschieden.

Weiterhin muss per Konvention nach jedem schließenden Tag zwingend ein Zeilenumbruch erscheinen. Vor einem öffnenden Tag dürfen per Konvention lediglich Whitespace-Zeichen eingefügt werden. Ein Tag kann entweder nur Textinhalt ("CData") oder weitere Tags enthalten, aber nicht beides gleichzeitig. Falls der Tag einen CDATA-Abschnitt enthält, müssen der Starttag und der Endtag auf der gleichen Zeile sein. Falls der Tag weitere Tags enthält, muss nach dem Starttag ein Zeilenumbruch erfolgen. Zeilenumbrüche in CDATA-Abschnitten können durch die Escapesequenz "\n" ausgedrückt werden.

Alle CDATA-Abschnitte außerhalb eines Tags oder Abschnitte welche nicht der Syntax entsprechen, werden als Kommentare behandelt und bei der Verarbeitung der Datei ignoriert. Eine besondere Markierung von CDATA-Abschnitten oder Kommentaren, wie in XML üblich, entfällt.

Die Verwendung der XML-typischen Schreibweise für leere Tags, beispielsweise "<br />" ist nicht gestattet (verwenden sie "<br></br>" stattdessen).

Abschließend soll gelten, dass auf die Verwendung von Attributen verzichtet werden soll.

Der Grund für diese recht restriktive Syntax wird deutlicher bei Betrachtung eines einfachen Beispiels.

Beispiel

Im Folgenden sollen Beispiele beschrieben werden, welche zeigen, auf welche Weise native Datentypen in PHP-Skripten durch das SML-Format darstellbar sind.

skalare Variablen

Darstellung in PHP-Code:
<?php
$a = 1;
$b = 'string';
$c = 12.5;
$d = true;
?>
äquivalente Darstellung in SML:
<a>1</a>
<b>string</b>
<c>12.5</c>
<d>true</d>

An dieser Stelle ist es wichtig eine syntaktische Einschränkungen von PHP zu verstehen. Eine PHP-Funktion kann nur einen einzelnen Rückgabewert besitzen. (Der Fall, dass der Funktion Parameter per Referenz übergeben werden, wird hier nicht betrachtet.) Eine PHP-Funktion welche den Inhalt des SML-Dokuments auswertet und als Rückgabewert liefert, ist daher gezwungen, die Inhalte in Form eines Arrays zu repräsentieren. Die Inhalte dieses Arrays können wiederum in Variablen innerhalb des Kontext des aufrufenden Programmfragments kopiert werden, wodurch der ursprüngliche Zustand wiederhergestellt wird.

Um ein zweites Beispiel zu nennen: Dokumente in JSO-Notation unterliegen den gleichen Einschränkungen.

numerische Datenfelder
Darstellung in PHP-Code:
<?php
$A = array();
$A[0] = 1;
$A[1] = 'string';
$A[2] = 12.5;
$A[1000] = true;
$B = array();
$B[0] = 2;
?>
äquivalente Darstellung in SML:
<A>
    <0>1</0>
    <1>string</1>
    <2>12.5</2>
    <1000>true</1000>
</A>
<B>
    <0>2</0>
</B>
assoziative Datenfelder
Darstellung in PHP-Code:
<?php
$SCREEN = array();
$SCREEN["width"] = 1024;
$SCREEN["height"] = 768;
$SCREEN["depth"] = "32-Bit";
?>
äquivalente Darstellung in SML:
<SCREEN>
    <width>1024</width>
    <height>768</height>
    <depth>32-Bit</depth>
</SCREEN>
mehrdimensionale und gemischte Datenfelder
Darstellung in PHP-Code:
<?php
$A = array();
$A["a"] = 1;
$A["b"] = 2;
$A[0] = "drei";
$B = array();
$B[0] = true;
$B["a"] = 1000;
$B["b"] = array();
$B["b"][0] = 1;
$B["b"][1] = 2;
$B["b"]["a"] = 3;
?>
äquivalente Darstellung in SML:
<A>
	<a>1</a>
	<b>2</b>
	<0>drei</0>
</A>
<B>
	<a>1000</a>
	<b>
		<0>1</0>
		<1>2</1>
		<a>3</a>
	</b>
</B>

Wie aus den obigen Beispielen ersichtlich, eignet sich das beschriebene Format gut um skalare Variablen und Datenfelder darzustellen, welche üblicherweise als Parameter für die Initialisierung des Frameworks in Frage kommen dürften. Die Angabe eines Typs ist nicht erforderlich, weil PHP nicht streng typisiert ist. Der Typ einer Variablen ist zur Laufzeit folglich dynamisch. Die einzige notwendige Unterscheidung findet zwischen skalaren Werten und Datenfeldern statt. Diese Unterscheidung ist trivialerweise anhand der Syntax möglich.

Alternativen zu SML

Zu dem für dieses Framework verwendeten SML-Dateiformat gibt es eine Anzahl populärer Alternativen. Der folgende Abschnitt wird einige dieser Alternativen vorstellen, vergleichen und die Ergebnisse diskutieren.

Im Folgenden sollen verschiedene Teilaspekte betrachtet werden:

Da nicht ausgeschlossen werden kann, dass eine Bearbeitung des Quelltextes der Dateien teilweise von Hand erfolgen muss, ist der Lesbarkeit des Quelltextes ein Kriterium, das beleuchtet werden soll. Die Syntax sollte im Idealfall intuitiv zu erfassen sein. Insbesondere ist dies wichtig, da zum gegenwärtigen Zeitpunkt nur für eine Untermenge der Gesamtheit der Konfigurationsmerkmale des Frameworks eine grafische Oberfläche bereitgestellt werden kann. In Anbetracht der Fülle an Optionen ist es darüber hinaus auch auf absehbare Zeit eher unwahrscheinlich, dass eine vollständige Abdeckung erreicht werden kann. Es stellt sich ohnehin die Frage, ob dies überhaupt wünschenswert wäre. Schließlich sollte auch berücksichtigen werden, dass es prinzipiell erfahrene Anwender gibt, welche bewusst und absichtlich auf die Funktionen einer "schwerfälligen" GUI verzichten, weil sie diese eher als Behinderung anstatt als Bereicherung empfinden.

Ein interessanter Faktor ist auch die Performance, da das Dateiformat einem eventuell zeitkritischen Zweck genügen soll, nämlich der Initialisierung des Frameworks. Begründet dadurch, dass die Dateien bei jedem Aufruf des Frameworks neu gelesen und dabei eventuell auch durch einen Parser untersucht werden müssen bevor ihre Informationen verfügbar sind, sollte dieser Vorgang mit möglichst geringen Kosten im Hinblick auf die Rechenzeit auskommen. Nicht immer ist ein sinnvoller Vergleich möglich, wo sich ein Vergleich jedoch anbietet sollte er durchgeführt werden.

Darüber hinaus sollten die Grenzen des jeweiligen Dateiformats beachtet werden. Wenn es Faktoren gibt, welche dazu führen können, dass ein Einsatz unter bestimmten Bedingungen nicht mehr sinnvoll ist, sollten diese genannt werden.

XML-Parser

Die Portabilität der Dateien in andere Programmiersprachen ist eine der Stärken von XML. Parser für XML sind in den Funktionsumfang nahezu jeder modernen Skript- oder Programmiersprache integriert. Dies fällt jedoch für dieses Anwendungsgebiet – die Initialisierung des Frameworks – nicht ins Gewicht, da die für die Umsetzung des Frameworks gewählte Sprache ist PHP und Implementierungen des Frameworks in anderen Sprachen existieren zurzeit nicht.

Das aktuelle Werkzeug der Wahl zur Behandlung von XML, welches gleichermaßen für PHP 4 als auch PHP 5 verfügbar ist, ist zum gegenwärtigen Zeitpunkt der interne XML-Parser. Dieser XML-Parser besitzt allerdings eine Schwachstelle. Er ist lediglich zum Lesen von XML-Dateien verwendbar, nicht jedoch zum Schreiben. Eine Implementierung zum Erzeugen von XML-Dateien ist erst für PHP ab Version 5 als Standardkomponente enthalten.

Hinzu kommt, dass mithilfe des XML-Parsers ein assoziatives Datenfeld aus einer XML-Datei zu erstellen ähnlich viel Programmieraufwand benötigt, wie für das Schreiben eines Skripts für das Laden einer SML-Datei erforderlich gewesen ist. Allerdings ist dies mit dem Risiko verbunden, dass sich die Implementierung des XML-Parsers in einer späteren Veröffentlichung der Sprache möglicherweise verändert, auch wenn dies grundsätzlich unwahrscheinlich ist. Zudem gibt es keine sonstigen wesentlichen Vorteile dieser Implementierung, abgesehen von der allgemeinen Beliebtheit von XML als Dialekt.

Als weiteres Argument wäre die Performance zu beleuchten. Dies gestaltet sich jedoch alles andere als unproblematisch und die Ergebnisse sind nur unter Vorbehalt zu betrachten, da diese abhängig sind vom eingesetzten Werkzeug. Derer gibt es viele für das XML-Format, selbst wenn sich auf PHP als solches beschränkt wird.

Um einen Vergleich anstellen zu können, soll ein einfaches XML-Dokument geladen und in ein Datenfeld übertragen werden.

Zum Vergleich hier der Quelltext des verwendeten XML-Dokuments.

<?xml version="1.0"?>
<root>
     <array name="channel">
             <scalar name="title">Test</scalar>
             <scalar name="link">about:blank</scalar>
             <scalar name="description" />
             <scalar name="language">de-de</scalar>
             <array name="0">
                     <scalar name="title">Testeintrag 1</scalar>
                     <scalar name="pubDate">Do, 9 Jun 2005 13:23:18 +0200</scalar>
                     <scalar name="description"><![CDATA[Testeintrag]]></scalar>
                     <scalar name="link" />
                     <scalar name="author">Testautor</scalar>
             </array>
             <array name="1">
                     <scalar name="title">Testeintrag 2</scalar>
                     <scalar name="pubDate">Do, 9 Jun 2005 13:23:53 +0200</scalar>
                     <scalar name="description"><![CDATA[Testeintrag]]></scalar>
                     <scalar name="link" />
                     <scalar name="author">Testautor</scalar>
             </array>
             <array name="2">
                     <scalar name="title">Testeintrag 3</scalar>
                     <scalar name="pubDate">Do, 9 Jun 2005 13:24:18 +0200</scalar>
                     <scalar name="description"><![CDATA[Testeintrag]]></scalar>
                     <scalar name="link" />
                     <scalar name="author">Testautor</scalar>
             </array>
             <array name="3">
                     <scalar name="title">Linktest</scalar>
                     <scalar name="pubDate">Do, 9 Jun 2005 13:24:36 +0200</scalar>
                     <scalar name="description"><![CDATA[Testeintrag]]></scalar>
                     <scalar name="link">about:blank</scalar>
                     <scalar name="author">Testautor</scalar>
             </array>
     </array>
</root>

Anschließend das Gleiche im SML-Format.

<channel>
             <title>Test</title>
             <link>about:blank</link>
             <language>de-de</language>
             <0>
                     <title>Testeintrag 1</title>
                     <pubDate>Do, 9 Jun 2005 13:23:18 +0200</pubDate>
                     <description>Testeintrag</description>
                     <author>Testautor</author>
             </0>
             <1>
                     <title>Testeintrag 2</title>
                     <pubDate>Do, 9 Jun 2005 13:23:53 +0200</pubDate>
                     <description>Testeintrag</description>
                     <author>Testautor</author>
             </1>
             <2>
                     <title>Testeintrag 3</title>
                     <pubDate>Do, 9 Jun 2005 13:24:18 +0200</pubDate>
                     <description>Testeintrag</description>
                     <author>Testautor</author>
             </2>
             <3>
                     <title>Linktest</title>
                     <pubDate>Do, 9 Jun 2005 13:24:36 +0200</pubDate>
                     <description>Testeintrag</description>
                     <link>about:blank</link>
                     <author>Testautor</author>
             </3>
</channel>

Zum Vergleich wird PHP 4 mit dem im Standard enthaltenen XML-Parser herangezogen. Dabei wird so vorgegangen, dass vor und nach jedem Parsen jeweils mithilfe des Befehls "microtime" eine Messung durchgeführt wird. Die Differenz zwischen beiden Werten wird in Millisekunden ausgegeben. Es kommt dabei nicht darauf an, wie viele Millisekunden die eine oder andere Technik schneller ist. Das objektiv zu beurteilen ist mit diesem Testverfahren selbstverständlich unmöglich, denn das Verfahren ist viel zu rudimentär um repräsentative Ergebnisse zu liefern.

Die Konfiguration des Testsystems kann in diesem Fall vernachlässigt werden, da lediglich die Größenordnung der Differenz zwischen beiden Techniken betrachtet werden soll.

Äußert problematisch für eine objektive Bewertung ist zudem der unglückliche Umstand, dass der XML-Parser zur Behandlung der Start-Tags, End-Tags und CDATA-Bereiche Einschübe aus handgeschriebenem PHP-Code benötigt. Es wäre somit denkbar, dass Effekte durch mehr oder minder performanten PHP-Code das Ergebnis der Messung verfälschen. Daher wird der XML-Parser sowohl einmal mit einer vergleichbaren Implementierung, als auch ein zweites Mal zum Vergleich ohne irgendeine Implementierung gemessen.

Ziel des Tests ist es nicht, ein Votum zu treffen für oder gegen den Einsatz des XML-Parsers. Vielmehr soll sich zeigen, ob es deutliche Unterschiede zwischen beiden Varianten gibt. Insbesondere, ob die SML-Variante um Größenordnungen langsamer als der XML-Parser ist. Dies könnte einen Hinweis darauf liefern, dass die gefundene Lösung möglicherweise aus Gründen schlechter Performance nicht für das Framework geeignet sein könnte.

Für diese recht bescheidene Aufgabenstellung sollte diese äußert einfache Testmethode trotz allem ausreichend genaue Ergebnisse liefern.

XML-Parser 1 XML-Parser 2 SML-Skript Differenz
SML zu XML 1
Differenz
SML zu XML 2
0,003685s 0,001813s 0,001626s -0,001153s (31%) -0,000187s (10%)
0,003410s 0,001666s 0,001255s -0,002155s (63%) -0,000411s (24%)
0,003367s 0,001629s 0,001312s -0,002055s (61%) -0,000317s (19%)
0,003394s 0,001614s 0,001240s -0,002154s (63%) -0,000374s (23%)
0,003381s 0,001618s 0,001228s -0,002153s (63%) -0,000390s (24%)
0,003386s 0,001613s 0,001400s -0,001986s (59%) -0,000213s (13%)
0,003387s 0,001620s 0,001296s -0,002091s (61%) -0,000324s (20%)
0,003658s 0,001617s 0,001247s -0,002411s (65%) -0,000370s (22%)
0,003678s 0,001633s 0,001454s -0,002224s (60%) -0,000179s (10%)
0,003725s 0,001613s 0,001573s -0,002152s (58%) -0,000040s (2%)

Vergleich der Performance zwischen XML-Parser und SML-Skript (Auszug)

1 XML-Parser bei Verwendung einer zum SML-Skript vergleichbaren Implementierung

2 XML-Parser im Leerlauf, ohne Verarbeitung der Eingabe

Betrachtet man den obigen, kurzen Auszug der Ergebnisse so fällt einerseits auf, dass der mit PHP-Code bestückte XML-Parser weniger performant agiert hat als das SML-Skript. Dies könnte jedoch wie bereits erwähnt auch eine Frage weniger performanter Programmierung sein. Betrachtet man jedoch Spalte 2 ("XML-Parser 2") im Vergleich zu Spalte 3 ("SML-Skript") so sieht man, dass auch in diesem Fall die SML-Variante nah bei den Werten des XML-Parsers liegt. Dies ist insbesondere bemerkenswert, da der XML-Parser in diesem Fall gar kein Ergebnis produzierte, da keine Implementierung zur Bearbeitung des Inhalts angegeben wurde. Aus diesem Grunde kann das Argument, dass eine ungünstig gewählte Implementierung den XML-Parser verlangsamt haben könnte, nicht mehr aufrecht erhalten werden.

Dieser Test lieferte folglich keinen Hinweis darauf, dass die Leistungsfähigkeit der Implementierung einen negativen Effekt auf die Performance der gesamten Anwendung ausüben könnte.

SimpleXML

Syntaktisch gesehen unterscheidet sich die Benutzung von SimpleXML für den Entwickler nur unwesentlich von der Verwendung des SML-Skripts, wie der nachfolgende Quellcodeauszug verdeutlicht.

<?php
$sml = SML::getFile("test.config");
$xml = simplexml_load_file("test.xml");
?>


Der einzige offensichtliche Unterschied liegt im Typ des Rückgabewerts. Während die SML-Variante ein assoziatives Datenfeld als Ergebnis liefert, gibt SimpleXML ein Objekt vom Typ "SimpleXMLElement" zurück. Man mag geteilter Auffassung darüber sein, welche Variante die glücklichere Wahl ist.

Gegen SimpleXML spricht, dass es die Namen von Tags und Attributen auf Namen von Objekten und der Eigenschaften in PHP ab. Das ist problematisch, weil diese in PHP und XML jeweils unterschiedliche Zeichen enthalten dürfen. Zum Beispiel betrifft dies das Zeichen '-', welches in PHP nicht für die Benennung von Variablen verwendet werden darf. Folglich kann man zum Zeitpunkt der Erstellung dieses Dokuments über SimpleXML auf einen Tag namens <foo-bar> nur sehr umständlich zugreifen.

Initialisierungsdateien

Initialisierungsdateien, häufig abgekürzt mit der Dateiendung "ini", sind ihrerseits eine geeignete Alternative, sofern keine Abbildung von komplexen Strukturen erforderlich ist. Die Darstellung von Schlüsseln, insbesondere bei tief verschachtelten Informationen, kann jedoch im Einzelfall unübersichtlich werden. Das Format bietet syntaktisch einen einfachen Aufbau. Allerdings müssen dem Format einige Abstriche gegenüber XML zugestanden werden. Es fehlt zum Beispiel die typische Schreibweise in Form von Tags, welche derzeit populär ist. Das Erstellen einer DTD oder einer vergleichbaren Datei, welche die Struktur des Dateiformats beschreibt, ist sowohl praktisch als auch aus theoretischen Überlegungen heraus nicht möglich. Dies ist jedoch kein Nachteil. Bedenkt man, dass die vordergründige Aufgabe dieses Dateiformats darin besteht, eine Abbildung von beliebig strukturierten assoziativen Datenfeldern aus einer Skript- oder Programmiersprache heraus auf ein Dateiformat zu realisieren, wird deutlich, dass die Vorgabe einer statischen Struktur nicht sinnvoll ist. Ideal wäre eine Kombination, welche die Vorteile beider Formate in sich vereint.

Der folgende Quellcodeauszug zeigt ein Beispiel für eine Initialisierungsdatei.

[STORE\0]
type=book
author=Dr. A Beispiel
[STORE\0\TITLE]
main=Protomaterie
subtitle=Alpha et Omega
[STORE\1]
type=cd
author=Barbara Sänger
[STORE\1\TITLE]
main=Best-Of

JSON

Eine weitere Alternative ist die Verwendung von JSON. Im Folgenden ein Beispiel:

"STORE" : {
    "0" : {
        "type" : "book",
        "author" : "Dr. A Beispiel",
        "TITLE" : {
            "main" : "Protomaterie",
            "subtitle" : "Alpha et Omega"
        }
    },
    "1" : {
        "type" : "cd",
        "author" : "Barbara Sänger",
        "TITLE" : {
            "main" : "Best-Of"
        }
    }
}

Verwendung von "serialize" und "unserialize"

PHP bietet die Möglichkeit, ähnlich wie beispielsweise Java, mit den Befehlen "serialize" und "unserialize" Variablen zu serialisieren und wiederherzustellen.

Der folgende Quellcodeauszug zeigt ein Beispiel.

a:1:{s:7:"CHANNEL";a:7:{s:5:"TITLE";s:4:"Test";s:4:"LINK";s:11:"about
:blank";s:8:"LANGUAGE";s:5:"de-de";i:0;a:4:{s:5:"TITLE";s:13:"Testein
trag 1";s:7:"PUBDATE";s:29:"Do, 9 Jun 2005 13:23:18 +0200";s:11:"DESC
RIPTION";s:11:"Testeintrag";s:6:"AUTHOR";s:9:"Testautor";}i:1;a:4:{s:
5:"TITLE";s:13:"Testeintrag 2";s:7:"PUBDATE";s:29:"Do, 9 Jun 2005 13:
23:53 +0200";s:11:"DESCRIPTION";s:11:"Testeintrag";s:6:"AUTHOR";s:9:"
Testautor";}i:2;a:4:{s:5:"TITLE";s:13:"Testeintrag 3";s:7:"PUBDATE";s
:29:"Do, 9 Jun 2005 13:24:18 +0200";s:11:"DESCRIPTION";s:11:"Testeint
rag";s:6:"AUTHOR";s:9:"Testautor";}i:3;a:5:{s:5:"TITLE";s:8:"Linktest
";s:7:"PUBDATE";s:29:"Do, 9 Jun 2005 13:24:36 +0200";s:11:"DESCRIPTIO
N";s:11:"Testeintrag";s:4:"LINK";s:11:"about:blank";s:6:"AUTHOR";s:9:
"Testautor";}}}

Diese Lösung ist ohne Zweifel sehr performant. Der Befehl "unserialize" arbeitet mit dieser Eingabe noch einmal um den Faktor 2 schneller als SimpleXML. Problematisch ist jedoch die Lesbarkeit des erzeugten Datenstroms. Für händische Eingriffe ist diese Darstellung offensichtlich denkbar ungeeignet. Da eine gute Lesbarkeit für das Framework jedoch unabdingbar ist, wurde von einer Realisierung in dieser Form bis auf Weiteres abgesehen.

weiterführende Literatur

  1. Self-PHP, http://www.selfphp.info
  2. Offizielle PHP Webseite, http://www.php.net

Spam und Flooding

Definition

Unerwünschte Werbung in E-Mails, Foren oder Gästebüchern sind ein aktuelles Thema. In diesem Abschnitt wird erläutert, was man darunter versteht und es werden einige Methoden erläutert, mit denen Dritte "Spamming" oder "Flooding" betreiben. Anschließend wird gezeigt, auf welche Weise in diesem Framework versucht wird, diesen Bedrohungen zu begegnen.

Zwischen "Spam" und "Floods" gibt es trotz oberflächlicher Ähnlichkeiten einen feinen Unterschied, welcher im Folgenden dargelegt wird.

Unter "Spam" versteht man die mehrmalige, unaufgeforderte Übermittlung von medialen Inhalten an eine Person oder eine Gruppe von Personen. Beispielsweise das unaufgeforderte Versenden von E-Mails mit Werbeinhalten an Dritte. Aber auch massenhafte, unaufgeforderte Anrufe sind eine Form von "Spam". Der Versand von Spam ist in vielen Ländern (darunter Europa und die USA) illegal und wird strafrechtlich verfolgt.

Die Webseite "spamhaus.org" definiert "Spam" wie folgt.

The word " Spam " as applied to Email means Unsolicited Bulk Email ("UBE").

  1. (Bulk) the recipient's personal identity and context are irrelevant because the message is equally applicable to many other potential recipient
  2. (Unsolicited) the recipient has not verifiably granted deliberate, explicit, and still-revocable permission for it to be sent

A message is Spam only if it is both Unsolicited and Bulk.

Unter " Flooding " versteht man das mutwillige, unaufgeforderte "überfluten" eines Mediums mit Inhalten. Floods zielen darauf ab, den normalen Betrieb eines Mediums zu stören. Beispielsweise das massenhafte Veröffentlichen sinnfreier Texte in einem öffentlichen Forum. Aber auch eine Person, welche eine öffentliche Veranstaltung durch permanente Zwischenrufe stört, betreibt dem Grunde nach eine Form von Flooding. Flooding kann in einigen Fällen illegal sein. Beispielsweise dann, wenn ein wirtschaftlicher Schaden entsteht.

In der Regel wird "Spam" mit der Intention erstellt, Werbebotschaften zu vermitteln. Wohingegen "Floods" meist eher eine Form von Vandalismus darstellen.

Spam in Foren und Gästebüchern

Ein zunehmendes Problem stellt der Spam in Foren und Gästebüchern dar. Aber auch Blogs und Wikis sind betroffen. Meist werden solche Einträge zwar schnell aufgespürt und wieder entfernt, aber die Beseitigung unerwünschter Einträge dieser Art kostet Zeit und Geld. Im Folgenden Abschnitt wird beschrieben, auf welche Weise ein Angreifer dabei vorgehen könnte und es werden Mittel und Wege aufgezeigt, dem angemessen zu begegnen.

Der Angreifer geht dabei wie folgt vor. Zunächst sucht er ein anfälliges Skript eines Gästebuches oder Forums, welches eine ausreichend große Verbreitung im Internet besitzt. Er untersucht die Formulare zum Erstellen neuer Einträge und notiert die Bezeichnungen der erforderlichen Formularfelder. Der Angreifer späht bestimmte typische Texte innerhalb der Anwendung aus. Unter Verwendung dieser Texte als Suchbegriffe, findet er bei Suchdiensten Webseiten, auf denen das Skript installiert ist.

Der Angreifer erstellt eine Liste der URLs dieser Seiten, welche er in einer Datei ablegt. Mit Hilfe eines kurzen Programms trägt er, beispielsweise über einen anonymen Proxyserver, asynchron in einer einfachen Schleife Werbebotschaften in alle Formulare der Liste ein.

Wenn der Angreifer Glück hat, indexieren obendrein Suchmaschinen wie Google diese Seiten bevor der zuständige Administrator die Werbung entfernt. Auf diese Weise erhöhen in die Werbebotschaft eingebettete Hyperlinks obendrein den PageRank der so beworbenen Internetangebote, was dazu führen kann, dass diese bei Suchmaschinen leichter auf den vorderen Plätzen landen.

Es gibt mehrere Methoden solche Angriffe abzuwehren.

Reaktive Maßnahmen

Die einfachste Möglichkeit besteht darin, schlicht und ergreifend die URL zu ändern. Üblicherweise arbeiten die Skripte der meisten Angreifer asynchron. Es fällt dem Angreifer somit in der Regel nicht sofort auf, wenn eine Webseite nicht mehr erreichbar ist. Es ist davon auszugehen, dass der Angreifer um die URL zu korrigieren entweder auf das Update der Suchmaschine wartet, was durchaus 8 Wochen dauern kann, oder die Webseite selbst erneut besuchen und den neuen Link von Hand extrahieren muss. In beiden Fällen sollte das Opfer vorübergehend Ruhe vor dem Angreifer haben.

Für das Framework ist das Ändern der URL ohne Schwierigkeiten möglich. Das ist deshalb so einfach, weil das Framework beliebig viele durch eine ID-Kennung identifizierte Instanzen der installierten Anwendungen beziehungsweise Plugins in Form von "Konfigurationsprofilen" verwalten kann. Welche Profile aktiv sind und welche nicht, erschließt sich jedoch nur für den Webmaster selbst und nicht für den außenstehenden Nutzer.

Um die URL einer Anwendung zu ändern muss folglich lediglich das betroffene Profil umbenannt und neu verlinkt werden. Dies ist eine Frage von wenigen Minuten. Der positive Nebeneffekt besteht darin, dass der Angreifer selbst bei synchroner Übertragung, oder bei Prüfung der URL über ein automatisches Programm keinen Fehler 404 (Seite nicht gefunden) vom Server erhält. Selbst bei einer manuellen Prüfung bemerkt er durch einen direkten Aufruf der URL nicht, dass er ein inaktives Profil vor sich hat. Er wird je nach Konfiguration des Frameworks weiterhin Formulare aufrufen und (sofern das Profil nicht schreibgeschützt ist) Beiträge schreiben können.

Aus persönlicher Erfahrung kann ich berichten, dass sich Angreifer auf diese einfache Weise leicht monatelang in die Irre führen lassen, ohne ihren Fehler zu bemerken.

Eine weitere Maßnahme ist das Sperren von IPs oder IP-Blöcken. Das ist vor allem dann hilfreich, wenn der Angreifer stets die gleichen Proxyserver für seine Angriffe verwendet. Leider ist dies nicht häufig der Fall. Nichtsdestotrotz wurde diese Möglichkeit für das Framework berücksichtigt und eine entsprechende optionale Funktion eingebaut. Diese Funktion kann zudem auch dazu verwendet werden, bei Anwendungen in einem lokalen Netzwerk mit Zugang zum Internet den Zugriff auf die Anwendung auf das lokale Netzwerk zu beschränken und Zugriffe aus dem Internet zu untersagen.

Präventive Maßnahmen

Um von vorn herein zu verhindern, dass ein Angreifer mit einem automatischen Programm Einträge verfassen kann, gibt es die Möglichkeit in potentiell gefährdete Formulare Grafiken mit kombinierten Zahlen- und Buchstaben-Codes einzubauen. Um einen Eintrag schreiben zu können, muss der Besucher den eingeblendeten Code abtippen. Was für einen menschlichen Betrachter eine leichte Übung ist, gestaltet sich für ein automatisches Programm deutlich schwieriger.

Die Probleme welche sich für den Angreifer daraus ergeben sind vielfältig. Sein Programm muss zunächst erst einmal den aktuellen Code vom Server holen – selbst wenn es gelingt den Code zu extrahieren kostet dies in jedem Fall Zeit. Eine asynchrone Kommunikation ist daher nicht mehr möglich: die Anfrage muss gesendet und der Code muss empfangen werden. Dadurch besteht aber auch das Risiko, dass das Programm möglicherweise durch einen langsamen oder absichtlich modifizierten Server verlangsamt wird. Außerdem ist es mit deutlich größerem programmiertechnischen Aufwand verbunden.

Es ist davon auszugehen, dass ein Angreifer aus den zuvor genannten Gründen eine so geschütztes Webanwendung meiden wird.

Das Framework implementiert eine solche Codeabfrage. Die Standardbibliothek hält zu diesem Zweck die Aktionen "security_get_image" und "security_check_image" bereit, welche mit Hilfe der PHP GD-Bibliothek eine Grafik im PNG-Format erzeugen können und eine interne Codetabelle zum Vergleich der vom Nutzer eingegebenen Daten verwalten. Diese Tabelle wird durch eine ".htaccess" -Datei vor öffentlichen Zugriffen geschützt und in regelmäßigen Zeitabständen automatisch erneuert.

Vandalismus und Flooding in Foren und Gästebüchern

Flooding kann sowohl unbeabsichtigt als auch beabsichtigt sein.

Unbeabsichtigt kann dies beispielsweise dann leicht geschehen, wenn der Server vorübergehend stark belastet ist. In diesem Fall kann es passieren, dass ein einzelner Nutzer, der gerade einen Schreibzugriff auf die Datenbank in Auftrag gegeben hat, ungewohnt lange auf die Antwort des Servers warten muss. Aus Ungeduld kann es vorkommen, dass der Nutzer die Refresh-Funktion des Browser benutzt und somit die Daten ein zweites Mal an den Server sendet, was dazu führt, dass unbeabsichtigt zwei identische Einträge erstellt werden. Selbst wenn die Webseite selbst nur wenig besucht ist, kann dies dennoch recht häufig vorkommen, wenn die Webseite auf einem "shared server" gespeichert ist. Das heißt: wenn sich die Webseite, auf welcher das Framework installiert ist, einen Host mit anderen Kunden teilt. Es ist nicht unüblich, dass sich je nach Preiskategorie und Anbieter ohne Weiteres 1000 oder sogar 10000 verschiedene Kunden den gleichen Server und damit die gleichen Ressourcen teilen müssen.

Beabsichtigtes Flooding ist meist eine Form von "Vandalismus". Ziele des Angreifers ist es, die normale Nutzung der Seite zu stören beziehungsweise zu erschweren.

Sowohl beabsichtigtes als auch unbeabsichtigtes Flooding kann durch automatisierte Maßnahmen vermindert werden.

Beispielszenario

Es sollen zwei Methoden betrachtet werden, mit denen Nutzer den Betrieb der Anwendung versuchen könnten zu stören. Erstens: durch die Reihung überlanger Zeichenketten ohne Zeilenumbruch, Reihung einer überlangen Kette von Zeilenumbrüchen, überlangen Texten allgemein, oder übergroßer Grafiken, kann das Layout der Anwendung gestört werden. Dies bewirkt eventuell, dass Teile des grafischen Layouts nicht mehr so dargestellt werden, wie vom Entwickler beabsichtigt. Außerdem könnte es dazu führen, dass andere Nutzer umständlich scrollen müssen, weil die Darstellung anderer Beiträge dadurch beeinträchtigt wird.

Die zweite Methode ist das massenhafte Absetzen von irrelevanten Beiträgen. Dadurch wird es anderen Nutzern erschwert, wichtige Nachrichten zu erkennen und deren Inhalte zu nutzen. Der Angreifer sendet dazu mehrere identische, oder inhaltlich ähnliche Beiträge nacheinander an den Server.

Abwendung solcher Szenarien

Für die zweite Methode sieht das Framework folgende Lösung vor. Wenn zwei Beiträge nacheinander zur Speicherung vorgesehen werden, wird überprüft ob die Beiträge abgesehen vom Zeitindex den gleichen Inhalt haben. Ist dem so, dann wird der zweite Eintrag nicht gespeichert. Dies verhindert insbesondere unabsichtliches Flooding des Mediums, erschwert jedoch auch eventuelle Angriffe.

Zusätzlich gibt es eine Option, welche es erlaubt festzulegen, wie viele Einträge ein Nutzer prinzipiell nacheinander schreiben darf. Der Nutzer wird anhand der IP identifiziert. Ist die Option gesetzt und schreibt der Nutzer nacheinander mehr Einträge als vorgesehen, ohne dass ein anderer Nutzer in der Zwischenzeit auf einen der Beiträge geantwortet hat, dann wird dem Nutzer das Speichern weiterer Beiträge verweigert.

Für die Abwendung der ersten Methode sorgt eine Reihe von Filtern. Diese Filter beschränken die Textlänge, begrenzen die Größe für die Darstellung von Grafiken auf Maximalwerte, entfernen auffällige Wiederholungen und erzeugen zwangsweise Zeilenumbrüche, wenn eine Zeichenkette von mehr als 80 aufeinander folgenden Zeichen ohne Vorkommen eines Whitespace-Zeichen gefunden wird.

Diese Methoden erschweren einem Angreifer die Störung des normalen Betriebs, können aber dies nicht grundsätzlich verhindern. Dies wäre auch nicht unbedingt sinnvoll. Dies liegt an einem bekannten Dilemma. Verengt man den Trefferbereich der Filter, dann reduziert sich die Zahl der Falschmeldungen ("false-positives") von Einträgen, welche als Flood-Versuch erkannt werden, aber gar keine sind. Gleichzeitig schlüpfen jedoch auch eine höhere Anzahl echter Angriffe durch das Netz der Filter. Umgekehrt: erweitert man den Trefferbereich der Filter, fängt man mehr Angriffe ab. Allerdings erhöht sich auch die Zahl der "false-positives" dementsprechend. Im Endeffekt wird man somit stets einen "Trade-off" zwischen ausreichender Sicherheit und ausreichender Vermeidung von Falschmeldungen suchen.

weiterführende Literatur

  1. spamhaus.org
  2. PHP Manual. PHP Documentation Group, 23.3.2005, http://php.net/manual/en/

Verschlüsselung

Um die Sicherheit von Passwörtern zu erhöhen ist es sinnvoll diese zu verschlüsseln. Einwegverschlüsselungsverfahren [I] sind dazu gut geeignet. In diesem Abschnitt werden zwei der wichtigsten Vertreter beschrieben. In PHP sind diese über die Funktionen "md5()" beziehungsweise "crypt()" implementiert.

DES-Algorithmus

Das DES-Verfahren [II] war viele Jahre lang das Standard-Verschlüsselungsverfahren in den Vereinigten Staaten. Mit der Steigerung der Rechenleistung, welche in den letzten Jahren zu beobachten war, gilt das einfache DES-Verfahren inzwischen jedoch nicht mehr als sicher. Als sichere Modifikation gilt die dreifach Verschlüsselungsvariante "Triple-DES". Als Nachfolgeverfahren für DES wurde vom US-amerikanischen National Institute of Standards das so genannte RIJNDAEL-Verfahren AES [III] gewählt.

DES ist ein Verfahren welches auf der Binärdarstellung des Klartextes arbeitet. Es erzeugt zunächst eine initiale Permutation dieser Binärdarstellung. Anschließend wird eine Blockchiffre zur Verschlüsselung angewendet. Das DES-Verfahren ist eine Feistel-Chiffre. Feistel-Chiffren wenden mehrmals nacheinander eine interne Blockchiffre auf Teile der Nachricht an um eine Folge von Rundenschlüsseln zu erzeugen.

Für die Sicherheit von Feistel-Chiffren ist die Sicherheit der verwendeten internen Blockchiffre von entscheidender Bedeutung. Zurzeit wird DES immer noch als sicher genug für die meisten Alltagsanwendungen betrachtet und das Verfahren wird in vielen Umgebungen weiterhin verwendet. Beispielsweise findet DES Anwendung auf Unix-Systemen zur Authentifizierung von Nutzern.

MD5-Algorithmus

Der MD5-Algorithmus [IV] gehört zur Gruppe der Hashverfahren. Wichtig für die Sicherheit eines Hashverfahrens ist die Eigenschaft der Kollisionsfreiheit. Eine Kollision besteht immer dann, wenn für zwei verschiedene Klartexte der gleiche Chiffretext erzeugt wird. Falls eine Kollision gefunden wird, so ist es möglich mit Hilfe geeigneter Verfahren den Klartext zu berechnen. Es ist bekannt, dass MD5 nicht kollisionsfrei ist. Jedoch ist unbekannt, ob es überhaupt irgendeine Kompressionsfunktion gibt, welche gar keine Kollisionen aufweist. Daher gilt es für die Praxis als ausreichend, wenn es hinreichend schwierig ist eine Kollision zu finden. Derartige Verfahren werden als "kollisionsresistent" bezeichnet. Ebenso wichtig ist die Geschwindigkeit des Algorithmus, denn die Verschlüsselung selbst sollte – um für die Authentifizierung geeignet zu sein – möglichst effizient arbeiten.

Name des Verfahrens Blocklänge in Bit Geschwindigkeit in Prozent
MD4 128 100
MD5 128 68
RIPEMD-128 128 39
RIPEMD-160 160 24

Vergleich der Performance verschiedener Authentifizierungsverfahren

Die Sicherheit von MD5 ist inzwischen jedoch am Wanken [V]. Der Heise-Verlag berichtete zunächst Anfang 2005 darüber, dass es Forschern offensichtlich gelungen ist ein schnelleres Verfahren zur Berechnung von MD5-Hashs zu finden, [VI] wodurch das Auffinden von Kollisionen erleichtert würde. Kurze Zeit später, erschien die Meldung, dass es gelungen sei, unterschiedliche Zertifikate mit gleichem MD5-Hash [VII] zu erzeugen. Nur etwas mehr als ein halbes Jahr danach zeigte sich die vorläufige Spitze der Entwicklung [VIII], als eine Firma erstmals offiziell gegen Bezahlung die Dienstleistung anbot, MD5 und SHA1 Hashes mithilfe im Voraus berechneter Tabellen zu knacken, solange das Honorar stimmt. Es ist somit nur eine Frage der Zeit, wann das MD5-Verfahren für sensible Anwendungen nicht mehr genügend Sicherheit bieten wird.

Auch der eigentlich als sicherer geltende Algorithmus SHA-1 [IX], der mit einer Bitlänge von 160-Bit im Gegensatz zu MD5 mit 128-Bit aufwartet, ist jedoch bereits gebrochen. Wie Schneier berichtete [X], ist es einer Gruppe chinesischer Kryptoanalytiker (Xiaoyun Wang, Yiqun Lisa Yin, Hongbo Yu) von der Universität Shandong gelungen, eine Kollision in SHA-0 beziehungsweise SHA-1 zu finden. Für SHA-0 in 2 39 Operationsschritten, sowie für SHA-1 in 2 69 Schritten. Deutlich schneller also als der Brute-Force Ansatz mit etwa 2 80 erforderlichen Operationsschritten.

Das Framework verwendet ebenfalls MD5 zur Verschlüsselung von Passwörtern. Zusätzlich wird SHA-1 zum Erzeugen eindeutiger Session-Ids verwendet. Eine Umstellung der Passwortverschlüsselung von MD5 auf SHA-1 wird zu gegebener Zeit erfolgen.

weiterführende Literatur

  1. Prof. Dr. Buchmann, J.: Einführung in die Kryptographie, 2. Auflage. Springer-Verlag, 2001, Seiten 167 ff., 200 ff.
  2. FIPS PUB 197 - ADVANCED ENCRYPTION STANDARD. U.S. DEPARTMENT OF COMMERCE; National Institute of Standards and Technology, 26.11.2001 http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
  3. FIPS PUB 46-3 - DATA ENCRYPTION STANDARD. U.S. DEPARTMENT OF COMMERCE; National Institute of Standards and Technology, 25.10.1999 http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
  4. Rivest, R.: RFC 1321 - The MD5 Message-Digest Algorithm. MIT Laboratory for Computer Science / RSA Data Security Inc.,1992 http://www.faqs.org/rfcs/rfc1321.html
  5. Kaminsky, D.: MD5 To Be Considered Harmful Someday. http://www.doxpara.com/md5_someday.pdf
  6. Forscher erzeugen unterschiedliche X.509-Zertifikate mit gleichem MD5-Hash. Heise-Verlag, 03.03.2005 http://www.heise.de/newsticker/meldung/57038
  7. Verunsicherung um Sicherheit von Kryptoalgorithmen. Heise-Verlag, 18.08.2004 http://www.heise.de/security/news/meldung/50148
  8. Passwort-Cracker als Bezahldienst. Heise-Verlag, 11.11.2005 http://www.heise.de/security/news/meldung/66039
  9. FIPS PUB 180-1 - SECURE HASH STANDARD. U.S. DEPARTMENT OF COMMERCE; National Institute of Standards and Technology, 17.04.1995 http://www.itl.nist.gov/fipspubs/fip180-1.htm
  10. Schneier, Bruce: SHA-1 Broken. Weblog, 15.02.2005 http://www.schneier.com/blog/archives/2005/02/sha1_broken.html

Autor: Thomas Meyer, www.yanaframework.net