{{:hello_echo.jpg?150 |Ungewollte Ausgabe}}Wenn wir die Datei jetzt über //?go=helloworld// aufrufen, erhalten wir eine Ausgabe, die so ähnlich wie auf dem Bild aussehen sollte (roter Rahmen). Das führt uns zu einem ersten wichtigen Prinzip der FS2-Programmierung.
Um Inhalte an den vorgesehenen Stelle auszugeben, kann im Frogsystem 2 nicht einfach der PHP-Befehl [[http://php.net/manual/en/function.echo.php|echo]] verwendet werden. Am richtigen Platz ausgeben werden nur die Inhalte, die am Ende des Scripts in der Variable **$template** gespeichert sind.
Daher gibt es zwei Möglichkeiten um unseren Fehler zu korrigieren. Wir könnten //echo// weiter nutzen und die Ausgabe mit dem [[http://de2.php.net/manual/en/ref.outcontrol.php|PHP-Ausgabepuffer]] regeln, oder einfach //echo// durch **$template** ersetzen. In diesem Tutotial werden wir der Einfachheit halber die zweite Möglichkeit einsetzen. Dennoch sind beide Varianten prinzipiell gleichwertig.
$template = "Hello World";
Wenn wir uns jetzt die Seite anschauen, sieht das Ganze doch schon viel besser aus (oder sollte es zumindest).
===== Datenbank & Name =====
Nun wollen wir ja eigentlich mehr machen, als nur einen einfachen Text ausgeben und damit die Welt zu begrüßen. Eigentlich würden wir gerne alles mögliche begrüßen, und über das AdminCP einstellen können, wer gerade an der Reihe ist.
**Die Datenbank**
Das FS2 setzt im Hintergrund auf eine MySQL-Datenbank. Am einfachsten lässt sich diese über das Tool [[http://www.phpmyadmin.net|phpmyadmin]] verwalten, aber jeder andere Zugang ist natürlich genauso möglich.
Grundsätzlich verwendet das FS2 mehrere Tabellen, die dann die dann die entsprechenden Daten enthalten. Jede Tabelle beginnt dabei mit einem **Präfix**, dass während der Installation festgelegt wurde (Standard: fs2_, wird hier synonym für alle Präfixe verwendet). Es folgt dann der Name des Unter-Systems oder AddOns, für welche die Tabelle die **größte Relevanz** besitzt. Mit weiteren Unterstrichen können dann noch **Spezialisierungen** der Tabellen angegeben werden. So gibt es z.B. eine Tabelle //fs2_news//, die den Hauptinhalt von News speichert, aber auch eine Tabelle //fs2_news_config//, in der die Einstellungen für das News-System zu finden sind.
CREATE TABLE `fs2_hello_config` (
`id` TINYINT( 1 ) NOT NULL DEFAULT '1',
`hello_name` VARCHAR( 100 ) NULL DEFAULT 'World'
);
INSERT INTO `fs2_hello_config` (`id`,`hello_name`)
VALUES ('1', 'World');
**Ein Name muss her**
Bei der Erklärung, wie Tabellen Namen aufgebaut sind, ist dir vielleicht aufgefallen, dass dort von einem **Addon-Namen** die Rede ist. Diese Namen sind wichtig, damit sich sich verschiedenen Addons nicht in die Quere kommen.
Wenn wir unser Addon auf der offiziellen Seite einstellen möchten, wird unter anderem auch darauf geachtet, dass wir einen eindeutigen Addon-Namen gewählt haben. Festlegen müssen wir einen **Titel**, der Groß-/Kleinschreibung oder Sonderzeichen enthalten darf und einen **Tag**, der als **Präfix** z.B. bei Tabellen dient, klein geschrieben werden muss und keine Sonderzeichen enthalten darf, aber immer noch mit dem Titel in Verbindung stehen sollte.
///////////////////////
//// Update Config ////
///////////////////////
if (
$_POST['hello_name'] && $_POST['hello_name'] != ""
)
{
// security functions
$_POST['hello_name'] = savesql ( $_POST['hello_name'] );
// MySQL-Queries
mysql_query ( "
UPDATE `".$global_config_arr['pref']."hello_config`
SET
`hello_name` = '".$_POST['hello_name']."'
WHERE `id` = '1'
", $db );
// system messages
systext ( $TEXT["admin"]->get("changes_saved"),
$TEXT["admin"]->get("info"), FALSE, $TEXT["admin"]->get("icon_save_ok") );
// Unset Vars
unset ( $_POST );
}
/////////////////////
//// Config Form ////
/////////////////////
if ( TRUE )
{
// Display Error Messages
if ( isset ( $_POST['sended'] ) ) {
systext ( $TEXT["admin"]->get("changes_not_saved")."
".$TEXT["admin"]->get("form_not_filled"),
$TEXT["admin"]->get("error"), TRUE, $TEXT["admin"]->get("icon_save_error") );
// Load Data from DB into Post
} else {
$index = mysql_query ( "
SELECT *
FROM ".$global_config_arr['pref']."hello_config
WHERE `id` = '1'
", $db);
$config_arr = mysql_fetch_assoc($index);
putintopost ( $config_arr );
}
// security functions
$_POST['hello_name'] = killhtml ( $_POST['hello_name'] );
// Display Form
echo'
';
}
//siehe auch: [[example-admin-config|Beispiel & Erklärung einer Konfigurationsseite im AdminCP]]//
**Zugriffsrechte & Links anlegen**
Im AdminCP des Frogsystem 2 werden die Navigations-Menüs entsprechend der Zugriffsrechte eines eingeloggten Users gesetzt. Dazu muss jeder Seite ein entsprechendes Recht zugeordnet werden. Prinzipiell muss man für jede Seite ein Recht anlegen. Es kann nicht ein und dasselbe Recht für zwei Seiten genutzt werden. Es ist allerdings möglich Sub-Rechte zu definieren, die zusätzlich innerhalb einer Seite verwendet werden sollen.
Schauen wir uns dazu einmal die Tabelle **fs2_admin_cp** an:
* **page_id** Der Name des Rechts, i.d.R. Dateiname ohne Endung
* **group_id** ID der Linkgruppe, der die Seite zugeordnet ist
* **page_title** Der rechte Teil des Seitentitels
* **page_link** Link-Name, wie er im Menü erscheint
* **page_file** Name einer im Ordner "[FS2]/admin/" liegenden Datei (bei Sub-Rechten //page_link// des übergeordneten Rechts)
* **page_pos** Position innerhalb der Linkgruppe
* **page_int_sub_perm** Setze "1" für ein Sub-Recht
{{ :hello_table_admincp.jpg |Tabelle fs2_admin_cp}}
Bis auf die Linkgruppe sollte alles klar sein. Linkgruppen fassen die einzelnen Links innerhalb des Menüs optisch zu einer Gruppe zusammen. Diese Gruppen werden in der Tabelle **fs2_admin_groups** festgelegt:
* **group_id** ID der Linkgruppe, wird in //fs2_admin_cp// verwendet
* **group_title** Gruppenüberschrift
* **menu_id** ID eines Bereichs des oberen Menüs
* **group_pos** Position innerhalb eines Bereichs
{{ :hello_table_admingroup.jpg |Tabelle fs2_admin_group}}
Auch diese Tabelle sollte größtenteils selbsterklärend sein. **group_id** nutzt einfach einen fortlaufenden Index. **menu_id** bezieht sich auf das obere Menü, das selbst in der Tabelle //fs2_admin_cp// durch die Startseiten erzeugt wird, welche "-1" als //group_id// nutzen (und somit als Bereich inkl. zugehöriger Startseite definiert werden).
Addons sollten sich entweder in einen der bestehende Bereiche oder den Sonderbereich "AddOns" einbinden. Ein eigener Bereich muss bei der Überprüfung gesonderte Auflagen erfüllen.
Da es sich bei unserem AddOn um Inhalt handelt, wollen wir es auch entsprechend in den content-Bereich eingliedern, wir erstellen also folgende Gruppe:
INSERT INTO `fs2_admin_groups`
(`group_title`, `menu_id`, `group_pos`)
VALUES
('Hello!', 'content', '99');
Die 99 als Position innherhalb des Bereichs soll lediglich dafür sorgen, dass unser AddOn immer ganz unten angezeigt wird.
Mit der soeben erzeugten Gruppe können wir jetzt auch unserer eigentliches Recht bzw. den Link anlegen.
INSERT INTO `fs2_admin_cp`
(`page_id`, `group_id`, `page_title`, `page_link`, `page_file`, `page_pos`, `page_int_sub_perm`)
VALUES
('hello_config', '27', 'Konfiguration', 'Konfiguration', 'hello_config.php', '1', '0');
//group_id// variiert natürlich und muss später nur intern vom Installationsscript ermittelt werden. Einmal aus- und einloggen und wir finden unsere brandneue Konfigurationsseite im AdminCP. (Gilt nur für Admins, bei allen anderen Benutzern muss vorher natürlich noch über die Benutzerverwaltung das neue Recht gesetzt werden.)
{{ :hello_admin_config.jpg?400 |Hello! Konfigurationsseite}}
**Ausgabe anpassen**
Zu guter Letzt bauen wir in unsere Ausgabeseite helloworld.php noch die Abfrage des Config-Wertes aus der Datenbank ein:
//////////////////////
//// Config Array ////
//////////////////////
$index = mysql_query ( "
SELECT *
FROM `".$global_config_arr['pref']."hello_config`
WHERE `id` = '1'
", $db );
$config_arr = mysql_fetch_assoc ( $index );
$template = "Hello " . stripslashes ( $config_arr['hello_name'] ) . "!";
//siehe auch: [[example-frontend|Beispiel & Erklärung einer Frontend-Seite]]//
{{ :hello_db.jpg?250 |Ausgabe mit Wert aus Datenbank}}
Da wir uns dazu entschieden haben das Programm "Hello!" zu nennen, sollten wir eigentlich die Datei auch in "hello.php" umbenennen.
Da uns das aber zu viel Arbeit ist und da wir das Alias-System kennen lernen sollen, beleiben wir bei dem alten Namen und legen einen Alias an. Das geht ganz einfach unter System->Aliasse, die Maske ist selbsterklärend.
{{ :hello_admin_aliasse.jpg?400 |Alias hinzufügen}}
===== Templates =====
Nach dem wir schon den Inhalt der Begrüßung variabel gestaltet haben, wollen wir zum Schluss auch noch das Design über ein Template gestalten. Dazu müssen wir eine spezielle Template-Seite für das Admin-CP anlegen und abschließend die Ausgabe-Datei auf dieses neue Template zugreifen lassen.
**Template bearbeiten**
Die Template Bearbeitung findet im Admin-CP statt. Dazu wird ein normales PHP-Skript mit dem Namen **hello_template.php** angelegt, das aber intern auf eine besondere API zugreift. Wir speichern das Skript mit folgendem Inhalt:
// Set $go-Value
if ( $go == "tpl_hello" ) {
$TEMPLATE_GO = "tpl_hello";
} else {
$TEMPLATE_GO = "hello_template";
}
$TEMPLATE_FILE = "hello.tpl";
$TEMPLATE_EDIT = array();
$TEMPLATE_EDIT[] = array (
name => "HELLO",
title => "Hello!-Design",
description => "Darstellung der Hello!-Begrüßungsseite",
rows => 20,
cols => 66,
help => array (
array ( tag => "hello_name", text => "Name der Person oder Sache, die begrüßt werden soll." ),
)
);
// Intialise Editor
echo templatepage_init ( $TEMPLATE_EDIT, $TEMPLATE_GO, $TEMPLATE_FILE );
//siehe auch: [[example-admin-template|Beispiel & Erklärung einer Template-Seite im AdminCP]]//
Die im Skript angegebene Template-Datei **hello.tpl** wird vom System beim ersten Speichern automatisch erzeugt.
Die Einbindung der Seite funktioniert wie gehabt über das Rechte-System. Da wir wollen, dass die Template-Bearbeitung sowohl in der AddOn-Gruppe "Hello!", als auch unter **Styles->Templates** angezeigt wird, legen wir zwei Einträge an:
INSERT INTO `fs2_admin_cp`
(`page_id`, `group_id`, `page_title`, `page_link`, `page_file`, `page_pos`, `page_int_sub_perm`)
VALUES
('hello_template', '27', 'Template bearbeiten', 'Template', 'hello_template.php', '2', '0'),
('tpl_hello', '22', '„Hello!“ bearbeiten', 'Hello!', 'hello_template.php', '99', '0')
{{ :hello_template_navi.jpg?250 |Eintrag in zwei Menü-Gruppen}}
Hello {..hello_name..}!
Das Ausgabe-Skript wird nun noch wie folgt angepasst:
//////////////////////
//// Config Array ////
//////////////////////
$index = mysql_query ( "
SELECT *
FROM `".$global_config_arr['pref']."hello_config`
WHERE `id` = '1'
", $db );
$config_arr = mysql_fetch_assoc ( $index );
//////////////////////
//// Get Template ////
//////////////////////
$template = new template();
$template->setFile("hello.tpl");
$template->load("HELLO");
$template->tag("hello_name", stripslashes ( $config_arr['hello_name'] ) );
$template = $template->display();
//siehe auch: [[example-frontend|Beispiel & Erklärung einer Frontend-Seite]]//
Wenn wir uns jetzt die Ausgabe anschauen, können wir feststellen, dass unser AddOn endlich fertig ist:
{{ :hello_frontend_tpl_output.jpg?400 |Ausgabe einer Frontend-Seite in Abhängigkeit von einem Template}}
===== Installation & Deinstallation =====
Jedes AddOn muss ein eigenes Installations und Deinstallations-Skript mitbringen. Da für die aktuelle Version (Alix 5) keine allgemeine Form dieser Skritpe vorgesehen ist, sind wir beim Erstellen mehr oder weniger frei. Dennoch gibt es einige Hinweise die wir beachten müssen:
**Allgemein**
* AddOns sollten möglichst keine bestehenden Systeme (d.h. Dateien und Tabellen) verändern
* Alles was eingefügt wurde, muss auch wieder entfernt werden können
**Installation**
* Installations-Skripte sollten keine Dateien verschieben
* Dateien sollten bereits über die Ordnerstruktur eingefügt werden
* Es sollte ein Original-Template im Ordner "[FS2]/styles/default" abgelegt werden
* Installations-Skripte könnten erkennen ob evtl. vorhandene Dateninhalte aus einer vorherigen Installation des AddOns existieren und diese auf Wunsch übernehmen oder löschen
**Deinstallation**
* Prinzipiell müssen alle in die Datenbank eingefügten Daten entfernt werden
* Es könnte aber eine Option angeboten werden, inhaltliche Daten zu behalten
* Dateien sollten nur auf Nachfrage mit genauer Auflistung gelöscht werden
//siehe auch: [[example-de-install-script|Beispiel & Erklärung eines De- bzw. Installations-Skripts]]//