Startseite < Informatik < Algorithmen Datenstrukturen / Software-Engineering < Entwicklungsmodelle Entwicklungsphasen / Web-Engineering < Web-CMS < [ DRUCK , 2004 , 2005 , 2006 , 2007 , 2008 , 2009 ] Web-CMS-Beispiel > Webdesign Mashup Werbung > > / Programmiersprachen / Künstliche Intelligenz > Schach Privates / Inhalt >
Web-CMS-Beispiel
Eine editierbare Web-Visitenkarte als Web-CMS.
Vorwort Vorwort zum Beispiel
Kein 'Hallo Welt!'
Content-Management-Systeme (CMS) sind von Natur aus sehr umfangreiche Systeme.
Ein CMS muss dem Benutzer die Möglichkeit geben, die Inhalte (Content) des Systems ohne Programmiervorkenntnisse abändern zu können. Die Hauptaufgaben des CMS sind:
  • Inhalte persistent speichern
  • diese gespeicherten Inhalte anzeigen
  • dem berechtigten Benutzer die Bearbeitung dieser Inhalte ermöglichen
Kurzbeispiele für CMSe sind aufgrund des Umfanges kaum machbar, oder haben Sie schon einmal von einem CMS-Hallo-Welt-Programm gehört?

Auf dieser Seite präsentiere ich Ihnen ein vollständiges Web-CMS-Beispiel, welches leider etwas länglich wirkt — aber viel kürzer geht es halt fast nicht! :-(
Web-Visitenkarte als Beispiel
Selbstverständlich kann man für alles Mögliche ein CMS entwickeln, will man aber ein kürzeres CMS-Beispiel entwickeln, ist man gezwungen folgende Mängel in Kauf zu nehmen:
  • Rudimentäre Speicherverwaltung
  • Minimalistische Benutzerverwaltung
  • Mangelhafte Sicherheit
  • Vernachlässigte Usability
Mein Miniaturbeispiel zeigt die Realisierung einer bearbeitbaren Web-Visitenkarte in PHP. Mit PHP ist es mir möglich einen relativ kurzen Programmcode zu schreiben, das Serialisieren von Objekten ist gratis gegeben. Für eine Visitenkarte gibt es in der Regel nur einen Benutzer, so kann ich mir die Benutzerverwaltung mehr oder weniger sparen.

Wer das Beispiel schon mal in Aktion sehen will, kann sich das Beispiel, von dem hier die Rede ist, unter folgendem Link ansehen:
  1. Web-Visitenkarte in Aktion

    Wenn die Inhalte des aktiven Beispiels nicht den Inhalten des folgenden Beispiels entsprechen, liegt das lediglich daran, dass ich die Möglichkeiten des CMS-Beispiels bereits nutzte; es handelt sich nicht um ein anderes Programm, sondern um andere Inhalte. Gerade das macht doch die Daseinsberechtigung eines CMS aus!

    Einzige Änderung, die ich im Programmcode vorgenommen habe, betrifft die Benutzerkennung: USERNAME und PASSWORD.
Verwendung auf eigene Gefahr!
Vorliegendes CMS-Beispiel soll lediglich die Prinzipien eines CMS verdeutlichen, aus diesem Grunde kommt der Aspekt Sicherheit leider zu kurz. Das hier vorgestellte CMS-Beispiel ist beispielsweise nicht sicher vor Hackangriffen!
Beispiel Das CMS-Beispiel 'Visistenkarte'
Web-Visitenkarte
Realisiert wird hier eine anspruchslose Web-Visitenkarte mit folgenden editierbaren Inhaltskomponenten:
  • $title (Überschrift)
  • $owner (Inhaber der Visitenkarte)
  • $streat (Straße und Hausnummer)
  • $zip (Postleitzahl)
  • $city (Wohnort)
  • $code (HTML-Code für rechts oben; z. B. für Photo, für Werbung, etc.)
  • $infos (Liste von Zusatzinformationen)
    • $info->label (Überschrift einer Zusatzinformation)
    • $info->text (Text einer Zusatzinformation)
Laufzeitumgebung
Das hier vorgestellte CMS-Beispiel benötigt serverseitig mindestens PHP 4.0.x als Laufzeitumgebung und clientseitig einen beliebigen Internet-Browser 1 zur Anzeige/Bearbeitung der Visitenkarte. Dieses Beispiel kommt absolut ohne Datenbank aus.
Dateien
Das CMS-Beispiel Visitenkarte (Card) benötigt nur eine einzige Datei:
  1. index.php
Die Content-Datei (content.txt) wird beim ersten Aufruf von index.php automatisch erstellt, falls nicht vorhanden. Es ist also keine besondere Installation erforderlich.
index.php
<?php

/*****************************************************
 * Meine Visitenkarte (Card) Version 1               *
 *****************************************************
 * Simples Beispiel eines Web-CMS von Stefan K. Baur *
 *****************************************************/

// -- CONFIG ----------------------

define("USERNAME", "test"); // bitte ändern!
define("PASSWORD", "test"); // bitte ändern!

define("ROOT", "index.php"); // Einstiegspunkt.
define("CONTENT_FILE", "./content.txt"); // Content-Datei

// -- POST-Paramters --------------

$do = $_POST["do"];
$username = $_POST["username"];
$password = $_POST["password"];

$title = $_POST["title"];
$code = $_POST["code"];
$owner = $_POST["owner"];
$streat = $_POST["streat"];
$zip = $_POST["zip"];
$city = $_POST["city"];
$labels = $_POST["labels"];
$text = $_POST["text"];

// -- FUNCTIONS -------------------

// Liest den Inhalt der Content-Datei als String.
function readContent() {
  $content = "";
  if (file_exists(CONTENT_FILE)) {
    $fileHandle = fopen(CONTENT_FILE, "r");
    while (!feof($fileHandle)) {
        $content .= fgets($fileHandle, 1024);
    }
    fclose($fileHandle);
  }
  return $content;
}

// Schreibt einen String in die Content-Datei.
function writeContent($content) {
  $fileHandle = fopen(CONTENT_FILE, "w");
  fwrite($fileHandle, $content, strlen($content));
  fclose($fileHandle);
  // Anschließend Zugriffsberechtigungen setzen
  chmod(CONTENT_FILE, 0600);
}

// Befreit einen String von speziellen Sonderzeichen.
function strip($value, $full = true) {
  $result = stripslashes($value);
  if ($full) $result = str_replace("\"", "'", $result);
  return str_replace("&gt;", ">", str_replace("&lt;", "<", $result));
}

// -- CLASSES ---------------------

class Info {}

/* Die Visitenkarte. */
class Card {

  var $title = "";
  var $code = "";
  var $owner = "";
  var $streat = "";
  var $zip = "";
  var $city = "";
  var $infos = null; // Array of Info

  function Card() {
    // Default-Einstellungen.
    $this->title = "Meine Visitenkarte!";
    $this->code = "<a href=\"http://www.stefan-baur.de\">Zur HP!</a>";
    $this->owner = "Stefan Baur";
    $this->streat = "Sperlingstraße 6";
    $this->zip = "90459";
    $this->city = "Nürnberg";
    $this->infos = array();
    $info = new Info(); // Nur ein Beispiel-Info.
    $info->label = "Web-CMS-Beispiel";
    $info->text = "Dies ist ein total simples Web-CMS-Beispiel.";
    $this->infos[] = $info;
  }

  function editVars() {
    // Initialisierung mit globalen Variablen, vergleiche outEdit()
    global $title, $owner, $streat, $zip, $city, $code, $labels, $text;
    $this->title = strip($title);
    $this->owner = strip($owner);
    $this->streat = strip($streat);
    $this->zip = strip($zip);
    $this->city = strip($city);
    $this->code = strip($code, false);
    $this->infos = array();
    for ($i = 0; $i < count($text); $i++) {
      if ($text[$i]) { // Es werden nur Infos hinzugefügt, die Text haben.
        $info = new Info();
        $info->label = strip($labels[$i]);
        $info->text = strip($text[$i], false);
        $this->infos[] = $info;
      }
    }
  }

  /* Methoden zur Ausgabe von HTML */

  function out($string, $spaces = 0, $eol = "\r\n") {
    echo str_repeat("  ", $spaces) . $string . $eol;
  }

  function build($login) {
    // Ausgabe des vollständigen HTML-Dokuments.
    $this->out("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"");
    $this->out("\"http://www.w3.org/TR/html4/loose.dtd\">", 6);
    $this->out("<html>");
    $this->outHtmlHead(1);
    $this->outHtmlBody($login, 1);
    $this->out("</html>");
  }

  function outHtmlHead($s = 0) {
    $this->out("<head>", $s);
    $this->out("<title>" . $this->title . "</title>", $s + 1);
    $this->out("<meta http-equiv=\"content-language\" content=\"de\">", $s + 1);
    $this->out("<meta http-equiv=\"content-type\"", $s + 1, "");
    $this->out(" content=\"text/html; charset=ISO-8859-1\">", 0);
    $this->out("<meta http-equiv=\"content-style-type\"", $s + 1, "");
    $this->out(" content=\"text/css\">", 0);
    $this->out("<style type=\"text/css\">", $s + 1);
    $this->out("<!--", $s + 1);
    $this->outCSS($s + 2);
    $this->out("-->", $s + 1);
    $this->out("</style>", $s + 1);
    $this->out("</head>", $s);
  }

  function outCss($s = 0) {
    $this->out("* {", $s);
    $this->out("font-family : Verdana, Arial;", $s + 1);
    $this->out("}", $s);
    $this->out("body {", $s);
    $this->out("padding : 60px;", $s + 1);
    $this->out("}", $s);
    $this->out("input, textarea {", $s);
    $this->out("margin : 2px;", $s + 1);
    $this->out("font-family : \"Courier New\";", $s + 1);
    $this->out("font-size : 11pt;", $s + 1);
    $this->out("}", $s);
  }

  function outHtmlBody($login, $s = 0) {
    $this->out("<body>", $s);
    // Titel als Hauptüberschrift ausgeben.
    $this->out("<h1>" . $this->title . "</h1>", $s + 1);
    $this->out("<table width=\"100%\">", $s + 1);
    $this->out("<tr>", $s + 2);
    // Adresse ausgeben.
    $this->out("<td>", $s + 3);
    $this->out("<p>", $s + 4);
    $this->out("<b>" . $this->owner . "</b>", $s + 5);
    $this->out("<br>", $s + 5);
    $this->out($this->streat, $s + 5);
    $this->out("<br>", $s + 5);
    $this->out($this->zip, $s + 5);
    $this->out($this->city, $s + 5);
    $this->out("</p>", $s + 4);
    $this->out("</td>", $s + 3);
    // Code (HTML) ausgeben.
    $this->out("<td>" . $this->code . "</td>", $s + 3);
    $this->out("</tr>", $s + 2);
    $this->out("</table>", $s + 1);
    // Die Infoliste ausgeben.
    foreach ($this->infos as $info) {
      $this->out("<hr>", $s + 1);
      if ($info->label) {
        $this->out("<h2>" . $info->label . "</h2>", $s + 1);
      }
      $this->out("<p>" . $info->text . "</p>", $s + 1);
    }
    // Ausgaben für Benutzerinteraktion.
    if ($login) {
      $this->outEdit($s + 1);
      $this->outLogout($s + 1);
    } else {
      $this->outLogin($s + 1);
    }
    $this->out("</body>", $s);
  }

  function outInput($hint, $type, $name, $value, $s = 0) {
    // HTML-Input-Tag
    if ($hint) $this->out("<small>" . $hint . ":</small><br>", $s);
    $input = "<input";
    if ($type) $input .= " type=\"" . $type . "\"";
    if ($name) $input .= " name=\"" . $name . "\"";
    if ($value) $input .= " value=\"" . $value . "\"";
    $input .= ">";
    $this->out($input, $s);
  }

  function outTextarea($hint, $name, $value, $s = 0) {
    // HTML-Textarea-Tag
    if ($hint) $this->out("<small>" . $hint . ":</small><br>", $s);
    $textarea1 = "<textarea cols=\"80\" rows=\"5\"";
    if ($name) $textarea1 .= " name=\"" . $name . "\"";
    $this->out($textarea1, $s);
    $val = str_replace(">", "&gt;", str_replace("<", "&lt;", $value));
    $textarea2 = ">" . $val . "</textarea>";
    $this->out($textarea2, $s + 1);
  }

  function outEdit($s = 0) {
    $this->out("<hr>", $s);
    $this->out("<h2>Content bearbeiten</h2>", $s);
    $this->out("<form action=\"" . ROOT . "\" method=\"POST\">", $s);
    $this->outInput("", "hidden", "do", "edit", $s + 1);
    $this->outInput("", "hidden", "username", USERNAME, $s + 1);
    $this->outInput("", "hidden", "password", PASSWORD, $s + 1);
    // Editierbare Variablen: titel, owner, streat, ...
    $this->outInput("Titel", "text", "title", $this->title, $s + 1);
    $this->out("<br>", $s + 1);
    $this->outInput("Inhaber", "text", "owner", $this->owner, $s + 1);
    $this->out("<br>", $s + 1);
    $this->outInput("Straße", "text", "streat", $this->streat, $s + 1);
    $this->out("<br>", $s + 1);
    $this->outInput("Ort", "text", "zip", $this->zip, $s + 1);
    $this->outInput("", "text", "city", $this->city, $s + 1);
    $this->out("<br>", $s + 1);
    $this->outTextarea("Code", "code", $this->code, $s + 1);
    $this->out("<br>", $s + 1);
    // Editierbare Infos.
    $num = 0;
    foreach ($this->infos as $info) {
      $hint = ($num + 1) . ". Info";
      $this->outInput($hint, "text", "labels[" . $num . "]", $info->label, $s + 1);
      $this->out("<br>", $s + 1);
      $this->outTextarea("", "text[" . $num . "]", $info->text, $s + 1);
      $this->out("<br>", $s + 1);
      $num++;
    }
    // Zum Hinzufügen eines neuen Infos eine weitere Info-Eingabemöglichkeit.
    $this->outInput("Info hinzufügen", "text", "labels[" . $num . "]", "", $s + 1);
    $this->out("<br>", $s + 1);
    $this->outTextarea("", "text[" . $num . "]", "", $s + 1);
    $this->out("<br>", $s + 1);
    // Änderungen werden mit diesem Buttom wirksam, siehe CONTROLLER
    $this->out("<br>", $s + 1);
    $this->outInput("", "submit", "", "Alles speichern", $s + 1);
    $this->out("</form>", $s);
  }

  function outLogout($s) {
    // Der Benutzer kann sich ausloggen.
    $this->out("<hr>", $s);
    $this->out("<h2>Logout</h2>", $s);
    $this->out("<a href=\"" . ROOT . "\">Abmelden</a>", $s);
  }

  function outLogin($s) {
    // Der Benutzer kann sich einloggen.
    $this->out("<hr>", $s);
    $this->out("<h2>Login</h2>", $s);
    $this->out("<form action=\"" . ROOT . "\" method=\"POST\">", $s);
    $this->outInput("", "hidden", "do", "login", $s + 1);
    $this->outInput("", "text", "username", "", $s + 1);
    $this->outInput("", "password", "password", "", $s + 1);
    $this->outInput("", "submit", "", "Anmelden", $s + 1);
    $this->out("</form>", $s);
  }
}

// -- CONTROLLER ------------------ (Hauptprogramm)

// Vistenkarte mit Default-Einstellungen erzeugen.
$card = new Card();

// Visitenkarte aus Datei laden, falls vorhanden,
// ansonsten Default-Einstellungen in die Datei serialisieren.
$content = readContent();
if ($content) $card = unserialize($content);
else writeContent(serialize($card));

// Falls korrekte Login-Daten vorliegen,
// kann der Benutzer die Visitenkarte bearbeiten.
if (($username == USERNAME) && ($password == PASSWORD)) {
  if ($do == "login") {
    $card->build(true); // Visitenkarte in Bearbeiten-Modus anzeigen.
  } elseif ($do == "edit") {
    $card->editVars(); // Daten des HTML-Formulars lesen.
    writeContent(serialize($card)); // Neue Daten speichern.
    $card->build(true); // Visitenkarte in Bearbeiten-Modus anzeigen.
  } else {
    $card->build(false); // Visitenkarte anzeigen.
  }
} else {
  $card->build(false); // Standard-Ausgabe der Visitenkarte.
}

?>
Fragment von content.txt
O:4:"card":7:{s:5:"title";s:19:"Meine Visitenkarte!";s:4:"code";s:47: ...
Die Content-Datei content.txt stellt im Prinzip die Datenbank dar. Werden die Inhalte durch den Benutzer bearbeitet, so wird das Card-Objekt in die Content-Datei neu hineinserialisiert.

Im Folgenden sehen Sie der Vollständigkeit halber die beiden relevanten HTML-Ausgaben der Visitenkarte.
  • Wenn der Benutzer nicht angemeldet ist, wird „$card->build(false);” ausgeführt. Der Besucher kann dann die Inhalte nur lesen.
  • Wenn der Benutzer angemeldet ist, wird „$card->build(true);” ausgeführt. Der Benutzer kann dann die Inhalte bearbeiten.
Folgende Ausgaben werden automatisch mithilfe der build-Methode generiert und zur Laufzeit an den Browser weitergeleitet. Zur Installation benötigen Sie lediglich o. a. ‚index.php’.
$card->build(false);
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
            "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <title>Meine Visitenkarte!</title>
    <meta http-equiv="content-language" content="de">
    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
    <meta http-equiv="content-style-type" content="text/css">
    <style type="text/css">
    <!--
      * {
        font-family : Verdana, Arial;
      }
      body {
        padding : 60px;
      }
      input, textarea {
        margin : 2px;
        font-family : "Courier New";
        font-size : 11pt;
      }
    -->
    </style>
  </head>
  <body>
    <h1>Meine Visitenkarte!</h1>
    <table width="100%">
      <tr>
        <td>
          <p>
            <b>Stefan Baur</b>
            <br>
            Sperlingstraße 6
            <br>
            90459
            Nürnberg
          </p>
        </td>
        <td><a href="http://www.stefan-baur.de">Zur HP!</a></td>
      </tr>
    </table>
    <hr>
    <h2>Web-CMS-Beispiel</h2>
    <p>Dies ist ein total simples Web-CMS-Beispiel.</p>
    <hr>
    <h2>Login</h2>
    <form action="index.php" method="POST">
      <input type="hidden" name="do" value="login">
      <input type="text" name="username">
      <input type="password" name="password">
      <input type="submit" value="Anmelden">
    </form>
  </body>
</html>
$card->build(true);
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
            "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <title>Meine Visitenkarte!</title>
    <meta http-equiv="content-language" content="de">
    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
    <meta http-equiv="content-style-type" content="text/css">
    <style type="text/css">
    <!--
      * {
        font-family : Verdana, Arial;
      }
      body {
        padding : 60px;
      }
      input, textarea {
        margin : 2px;
        font-family : "Courier New";
        font-size : 11pt;
      }
    -->
    </style>
  </head>
  <body>
    <h1>Meine Visitenkarte!</h1>
    <table width="100%">
      <tr>
        <td>
          <p>
            <b>Stefan Baur</b>
            <br>
            Sperlingstraße 6
            <br>
            90459
            Nürnberg
          </p>
        </td>
        <td><a href="http://www.stefan-baur.de">Zur HP!</a></td>
      </tr>
    </table>
    <hr>
    <h2>Web-CMS-Beispiel</h2>
    <p>Dies ist ein total simples Web-CMS-Beispiel.</p>
    <hr>
    <h2>Content bearbeiten</h2>
    <form action="index.php" method="POST">
      <input type="hidden" name="do" value="edit">
      <input type="hidden" name="username" value="test">
      <input type="hidden" name="password" value="test">
      <small>Titel:</small><br>
      <input type="text" name="title" value="Meine Visitenkarte!">
      <br>
      <small>Inhaber:</small><br>
      <input type="text" name="owner" value="Stefan Baur">
      <br>
      <small>Straße:</small><br>
      <input type="text" name="streat" value="Sperlingstraße 6">
      <br>
      <small>Ort:</small><br>
      <input type="text" name="zip" value="90459">
      <input type="text" name="city" value="Nürnberg">
      <br>
      <small>Code:</small><br>
      <textarea cols="80" rows="5" name="code"
        >&lt;a href="http://www.stefan-baur.de"&gt;Zur HP!&lt;/a&gt;</textarea>
      <br>
      <small>1. Info:</small><br>
      <input type="text" name="labels[0]" value="Web-CMS-Beispiel">
      <br>
      <textarea cols="80" rows="5" name="text[0]"
        >Dies ist ein total simples Web-CMS-Beispiel.</textarea>
      <br>
      <small>Info hinzufügen:</small><br>
      <input type="text" name="labels[1]">
      <br>
      <textarea cols="80" rows="5" name="text[1]"
        ></textarea>
      <br>
      <br>
      <input type="submit" value="Alles speichern">
    </form>
    <hr>
    <h2>Logout</h2>
    <a href="index.php">Abmelden</a>
  </body>
</html>
Es bleibt wie immer Ihrem Ehrgeiz überlassen, dieses Beispiel im Hinblick auf Sicherheit und Usability zu verfeinern bzw. zu verbessern.