previous up next contents index
Next: 16 Kleines Bannerscript Up: 5 Beispiele Previous: 14 Einfaches Gästebuch

Subsections



15 Spruch des Abrufs

Was soll das Script eigentlich tun? Nun, es gibt häufiger den Spruch des Tages oder ähnliches. So etwas mit PHP zu realisieren wird schwierig. Wenn man einen Spruch des Tages realisieren will, hat man zwei Teilprobleme: Erstens muß man für diesen Tag einen Spruch auswählen und diesen zweitens anzeigen. Ersteres könnte man theoretisch dadurch lösen, daß man um Mitternacht ein Script aufruft, das den gewählten Spruch irgendwo speichert, von wo er dann den ganzen Tag lang ausgegeben werden kann.

PHP bietet allerdings von sich aus keine Möglichkeit, zu gewissen Zeiten irgendetwas automatisch zu machen. Die einzige Möglichkeit ist, mit einem Hilfsprogramm, wie z.B. CRON unter Unix, zum gewünschten Zeitpunkt das Ganze anzustoßen. Es gibt auch noch die Bastellösung, bei der bei der Ausgabe immer abgeprüft wird, ob es der erste Aufruf an diesem Tag ist und wenn ja, wird ein neuer Spruch ausgewählt.

Um das Ganze etwas einfacher zu halten, wird bei jedem Aufruf ein Spruch ausgewählt, der dann ausgegeben wird.

Kommen wir nun aber zum Programmieren. Als erstes stellt sich, wie immer, die Frage nach der Tabelle. Dies sollte hier kein großes Problem sein.

CREATE TABLE spruch (
  SID       int not null primary key auto_increment,
  Spruch    text,
  anzeigen  bool
);

CREATE unique INDEX spruch_idx_Spruch ON spruch (Spruch(200));

Neben dem eigentlichen Text und einem eindeutigen Schlüssel habe ich noch eine kleine Spalte anzeigen eingeführt, über die man später verhindern kann, daß ein Spruch angezeigt wird.

Viel interessanter ist die zweite Anweisung. Im Endeffekt will ich nur erreichen, daß ein Spruch nicht zweimal eingetragen werden kann. Im Prinzip kein Problem, ein UNIQUE im CREATE TABLE auf Spruch sorgt schon dafür, sollte man meinen. Dem ist aber leider nicht so, da Spruch vom Typ TEXT ist und dieser in Sachen Index etwas anders funktioniert als z.B. VARCHAR (d.h. er erlaubt keinen). Ab MySQL Version 3.23 ist es aber möglich, über diese zweite Anweisung einen Index auf eine TEXT-Spalte zu legen, wobei dann nur die ersten n Buchstaben genutzt werden (hier sind es 200).

Nachdem nun die Tabellenerstellung geklärt ist, kommen wir zu den eigentlichen PHP-Scripten. Hier stellt sich wieder die Frage, nämlich, in welcher Reihenfolge sie programmiert werden sollten. Ich habe mich für die folgende entschieden:

Kurze Begründung:
Das Einfügen in die Datenbank kann über ein einfaches SELECT von Hand überprüft werden. Der zufällige Spruch ist ja das eigentliche Ziel des Ganzen; hier könnte man jetzt auch schon fast aufhören; zumindest kann man jetzt das Ganze in Betrieb nehmen. Um einen Spruch zu löschen, muß man ihn irgendwie auswählen; deshalb die Gesamtausgabe vor dem Löschen. Über Löschen und anschließendes Einfügen kann man im Prinzip auch ändern; um das aber etwas komfortabler zu machen, gibt es als Letztes auch noch ein Ändern.

1 Neuen Spruch einfügen

Das folgende Script ist im Prinzip genauso aufgebaut, wie in 8.4 schon beschrieben. Im Prinzip sollte es durch die Kommentare selbsterklärend sein. Trotzdem noch zwei kleine Anmerkungen.

Es erfolgt keinerlei Authentifikation, d.h. jeder kann beliebige Daten in die Datenbank einfügen. Wie man eine entsprechende Paßwortüberprüfung einbauen könnte, steht im Kapitel 10.1.3.

In der Variable $anzeigen bzw. im Checkbox-Inputfeld wird nicht der Wert übergeben, der nachher in der Datenbank stehen soll (0 oder 1), sondern checked oder . Dadurch wird zwar die Wiederanzeige des Formulars einfacher, aber das Einfügen in die Datenbank etwas schwieriger. Es ist also eigentlich egal, wie man es realisiert.


<?php

// Verbindungsdaten MySQL DB
$DB_HOST = "localhost";
$DB_USER = "cr";
$DB_PASS = "123";
$DB_NAME = "cr";

$DatenOK = 1;
$Fehler = "";

if (isset($submit)){
  // Formular wurde submittet -> Daten prüfen
  if ($Spruch == ""){
    $DatenOK = 0;
    $Fehler .= "Bitte noch einen Text eingeben!";
  }

  if ($DatenOK){
    // Daten in DB eintragen
    mysql_connect($DB_HOST, $DB_USER, $DB_PASS)
      OR die("Konnte DB nicht erreichen!");
    mysql_select_db($DB_NAME)
      OR die("Konnte DB nicht erreichen");

    mysql_query(sprintf('INSERT INTO spruch 
                                (Spruch, anzeigen)
                         VALUES ("%s"  , %d)',
			$Spruch,
			($anzeigen == 'checked' ? 1 : 0)));
    switch (mysql_errno()){
    case 0:
      // Alles OK
      header('Location: http://'.$HTTP_HOST.
	     substr($PHP_SELF,0,strrpos($PHP_SELF,'/'))
	     .'/show_all.php4');
      exit;
      continue;
    case 1062:
      // Spruch doppelt eingetragen
      $DatenOK = 0;
      $Fehler .= "Den Spruch gibt es schon";
      continue;
    default:
      // Sonstiger Fehler
      // -> Fehlermeldung ausgeben
      $DatenOK = 0;
      $Fehler .= "MySQL: ".mysql_errno().": ".mysql_error();
    }
  }
}
else {
  // Werte vorbelegen
  $Spruch="";
  $anzeigen="checked";
}
?>
<html>
<head>
  <title>SDA eintragen</title>
</head>
<body>
<?php
if (!$DatenOK){
  echo "<h1>$Fehler</h1>";
}
?>
<form action="<?php echo $PHP_SELF; ?>" method="GET">
<center>

<textarea name="Spruch" rows="5" cols="80"><?php echo $Spruch; 
?></textarea><p>

Spruch anzeigen <input type="checkbox" name="anzeigen" 
value="checked" <?php echo $anzeigen; ?>><p>

<input type="submit" name="submit" value=" Alles OK ">

</center>
</form>
</body>

2 Zufälligen Spruch ausgeben

Das ist jetzt fast der einfachste Teil des Ganzen. Wie man einen zufälligen Datensatz auswählt, ist bereits im Kapitel 6.1 erklärt, von daher spare ich mir hier die Erklärung.

Ansonsten sollte das Script eigentlich selbsterklärend sein. In der ersten Datei, die ich sda.php4 genannt habe, wird eine Funktion get_spruch() realisiert. Diese kann dann später aus beliebigen anderen Dateien per include() eingefügt werden.

<?php

function get_spruch(){
  // Verbindungsdaten MySQL DB
  $DB_HOST = "localhost";
  $DB_USER = "cr";
  $DB_PASS = "123";
  $DB_NAME = "cr";
  
  mysql_connect($DB_HOST, $DB_USER, $DB_PASS)
    OR die("Konnte DB nicht erreichen!");
  mysql_select_db($DB_NAME)
    OR die("Konnte DB nicht erreichen");
  
  $res = mysql_query('SELECT Spruch, SID*0+rand() AS sort
                      FROM spruch
                      WHERE anzeigen = 1
                      ORDER BY sort
                      LIMIT 1');

  if (!$row = mysql_fetch_array($res)){
    echo "Fehler im Script!";
  }

  return $row["Spruch"];
}

?>

Und um zu sehen, daß die Funktion tatsächlich funktioniert, hier noch ein sehr kompliziertes Script.

<?php
include('./sda.php4');
?>
<html>
<head>
</head>
<body>
<pre>
<?php echo get_spruch(); ?>
</pre>
</body>

3 Alle Sprüche ausgeben

Wie schon anfangs geschrieben, wird zur Administration eine Übersicht über alle existierenden Spruche benötigt. Dies soll hier realisiert werden. Dazu muß natürlich zu jedem Spruch noch ein Link zum Ändern bzw. Löschen angegeben werden. Die ID des zu ändernden bzw. löschenden Scripts wird per GET-Parameter an das dann noch zu schreibende Script übergeben.

Auch hier erfolgt keinerlei Paßwortabfrage oder ähnliches, das heißt jeder kann sich alle Sprüche ansehen.

Das Script ist nicht sehr elegant programmiert, aber es funktioniert.


<?php

// Verbindungsdaten MySQL DB
$DB_HOST = "localhost";
$DB_USER = "cr";
$DB_PASS = "123";
$DB_NAME = "cr";

mysql_connect($DB_HOST, $DB_USER, $DB_PASS)
     OR die("Konnte DB nicht erreichen!");
mysql_select_db($DB_NAME)
     OR die("Konnte DB nicht erreichen");

?>
<html>
<head>
  <title>SDA ansehen</title>
</head>
<body>
<center>
<a href="insertchange.php4">Neu einf&uuml;gen</a>
</center>
<ul>
<?php

$res = mysql_query('SELECT SID, Spruch
                    FROM spruch
                    ORDER BY SID');

while ($row = mysql_fetch_array($res)){
  printf('<li><pre>%s</pre>
<a href="insertchange.php4?SID=%d">&Auml;ndern</a> &nbsp;
<a href="delete.php4?SID=%d">L&ouml;schen</a>'."\n",
	 $row["Spruch"],
	 $row["SID"],
	 $row["SID"]);
}

?>
</ul>
</body>

4 Spruch löschen

Nachdem wir nun Sprüche eintragen und sogar ausgeben können, wäre es evtl. auch ganz praktisch, sie zu löschen[*]. Das Löschen ist eigentlich kein großes Problem; das Script braucht nur die ID des zu löschenden Spruchs und ruft dann ein DELETE auf. Den Aufruf für das Script haben wir ja eben schon geschrieben.

Nach dem Löschen kann man entweder eine Erfolgsmeldung ausgeben, oder einfach wieder auf z.B. die Übersichtsseite weiterleiten, was hier gemacht wird.


<?php

if (!isset($SID) || !is_numeric($SID)){
  die("Fehler");
}

// Verbindungsdaten MySQL DB
$DB_HOST = "localhost";
$DB_USER = "cr";
$DB_PASS = "123";
$DB_NAME = "cr";

mysql_connect($DB_HOST, $DB_USER, $DB_PASS)
     OR die("Konnte DB nicht erreichen!");
mysql_select_db($DB_NAME)
     OR die("Konnte DB nicht erreichen");

mysql_query(sprintf('DELETE FROM spruch
                     WHERE SID=%d',
		    $SID));
    
header('Location: '.$HTTP_REFERER);
?>

5 Spruch ändern

Und als letztes wäre es natürlich auch ganz nett, einen Spruch auch ändern zu können. Wer jetzt faul ist (und wer ist das nicht?) wird denken: Das HTML-Formular haben wir doch schon. Stimmt, deshalb benutzen wir das auch; allerdings nicht per Copy and Paste, sondern wir erweitern das Einfügen-Script ein wenig.

Die Änderungen sind eigentlich relativ einfach. Als erstes wird die Datenbankverbindung immer aufgebaut, da sie an mehreren Stellen benötigt wird (hätte man auch durch eine Funktion eleganter lösen können). Als nächstes muß bei der Datenprüfung nun auch die Spruch-ID geprüft werden. Hier beschränke ich mich auf die Prüfung, ob es eine Zahl ist. Die eigentliche SQL-Anweisung muß natürlich auch erweitert werden, die Fehlerabfrage kann dann jedoch wieder dieselbe sein. Schließlich müssen auch irgendwo die alten Werte geholt werden und als letztes wird das HTML-Formular so erweitert, daß es bei Bedarf auch noch die Spruch-ID wieder übergibt. Das waren dann auch schon alle Änderungen und wir haben unser Änderungsscript fertig.


<?php

// Verbindungsdaten MySQL DB
$DB_HOST = "localhost";
$DB_USER = "cr";
$DB_PASS = "123";
$DB_NAME = "cr";

$DatenOK = 1;
$Fehler = "";

mysql_connect($DB_HOST, $DB_USER, $DB_PASS)
     OR die("Konnte DB nicht erreichen!");
mysql_select_db($DB_NAME)
     OR die("Konnte DB nicht erreichen");
  

if (isset($submit)){
  // Formular wurde submittet -> Daten prüfen
  if ($Spruch == ""){
    $DatenOK = 0;
    $Fehler .= "Bitte noch einen Text eingeben!";
  }

  if (isset($SID)){
    // Eine Spruch-ID wurde übergeben
    // -> sie muß geprüft werden
    //
    // Überprüfung, ob sie tatsächlich existiert,
    // könnte auch noch erfolgen
    if (!is_numeric($SID)){
      $DatenOK = 0;
      $Fehler .= "Ungültige Spruch-ID übergeben!";
    }
  }

  if ($DatenOK){
    // Daten in DB eintragen
    if (isset($SID)){
      // Spruch-ID wurde übergeben
      // -> Spruch wird geändert
      mysql_query(sprintf('UPDATE spruch 
                          SET Spruch="%s", anzeigen=%d
                          WHERE SID=%d',
			  addslashes($Spruch),
			  ($anzeigen == 'checked' ? 1 : 0),
			  $SID));
    }
    else {
      // neuer Spruch -> einfügen
      mysql_query(sprintf('INSERT INTO spruch 
                                  (Spruch, anzeigen)
                           VALUES ("%s"  , %d)',
			  addslashes($Spruch),
			  ($anzeigen == 'checked' ? 1 : 0)));
    }

    // MySQL-Rückgabewert auswerten
    // Wenn OK -> Weiterleiten
    // sonst -> Fehlermeldung
    switch (mysql_errno()){
    case 0:
      // Alles OK
      header('Location: http://'.$HTTP_HOST.
	     substr($PHP_SELF,0,strrpos($PHP_SELF,'/'))
	       .'/show_all.php4');
      exit;
      continue;
    case 1062:
      // Spruch doppelt eingetragen
      $DatenOK = 0;
      $Fehler .= "Den Spruch gibt es schon";
      continue;
    default:
      // Sonstiger Fehler
      // -> Fehlermeldung ausgeben
      $DatenOK = 0;
      $Fehler .= "MySQL: ".mysql_errno().": ".mysql_error();
    }
  }
}
elseif (isset($SID)){
  // es soll der Spruch SID geändert werden
  // -> bisherigen Werte laden
  $res= mysql_query(sprintf('SELECT Spruch, anzeigen
                             FROM spruch
                             WHERE SID=%d',
			    $SID));

  if (!$row = mysql_fetch_array($res)){
    $DatenOK = 0;
    $Fehler .= "Konnte Spruch nicht laden";
  }
  $Spruch = $row["Spruch"];
  $anzeigen = ($row["anzeigen"] ? "checked" : "");
}
else {
  // Werte vorbelegen
  $Spruch="";
  $anzeigen="checked";
}
?>
<html>
<head>
  <title>SDA eintragen</title>
</head>
<body>
<?php
if (!$DatenOK){
  echo "<h1>$Fehler</h1>";
}
?>
<form action="<?php echo $PHP_SELF; ?>" method="GET">
<center>

<textarea name="Spruch" rows="5" cols="80"><?php echo $Spruch; 
?></textarea><p>

Spruch anzeigen <input type="checkbox" name="anzeigen" 
value="checked" <?php echo $anzeigen; ?>><p>

<?php
if (isset($SID)){
  // zum Ändern auch die SID übergeben
  printf('<input type="hidden" name="SID" value="%d">',
	 $SID);
}
?>

<input type="submit" name="submit" value=" Alles OK ">

</center>
</form>
</body>

6 Schlußbemerkung

Dieses Beispiel erhebt keine Anspruch darauf, ein elegant programmiertes Script zu sein. So ist es z.B. ungeschickt, die Datenbankverbingunsdaten in jede Datei zu schreiben. Eine Änderung und man muß jede Datei ändern. Es bietet sich also an, diese Daten in eine zentrale Datei zu speichern. Bei der Gelegenheit könnte man dann auch gleich noch den ganzen Datenbankverbindungsaufbau mit auslagern. Noch geschickter wäre natürlich die Verwendung von OOP, wie sie in Kapitel 17 beschrieben wird.

Ähnliches gilt für das HTML-Layout der Adminseiten[*]. Hier steht es fest in jeder Datei; flexibler wären dann z.B. HTML-Header und HTML-Footer Dateien, die jeweils per include() eingebunden würden.

Ein Programmieren mit Copy and Paste geht zwar am Anfang schneller, aber sobald man etwas ändern muß, wird es aufwendig, weil jede Stelle geändert werden muß. Beim Ändern hätte man auch das Einfügescript kopieren und dann anpassen können, dann hätte man sich die Abfragen gespart. Allerdings wäre der Aufwand beim Einfügen eines weiteren Feldes größer gewesen. Bei dieser Lösung muß an 4 Stellen erweitert werden: bei der Datenprüfung, den beiden SQL-Anweisungen und dem HTML-Formular. Bei der Kopierlösung müßte man zwei mal 3 Stellen ändern.


previous up next contents index
Next: 16 Kleines Bannerscript Up: 5 Beispiele Previous: 14 Einfaches Gästebuch
Christoph Reeg(http://reeg.net/)