CakePHP & DIEVOLUTION Blog
CakePHP Tutorial 1: Guestbook Anwendung
Endlich ist es Zeit für ein richtiges Tutorial. Denn mit dem aktualisierten Design soll natürlich auch aktuelles Material erscheinen. Daher gibt es nach dem weiterlesen ein richtig großes Tutorial zum Thema Guestbook, ich freue mich schon auf euer Feedback!
Dieses Tutorial wird euch eine Guestbook Anwendung für CakePHP zeigen. Es setzt vorraus, dass Cake auf dem gewünschten Server bereits installiert wurde und eine Verbindung zu einer MySQL Datenbank besteht.
Der Tutorialcode darf in Anwendungen verwendet werden, jedoch nicht als Tutorial unter fremden Namen weitervertrieben werden.
Benötigte Komponenten:
- CakePHP Version 1.1.X (ich verwende 1.1.15)
- Webserver & MySQL
Features dieses Guestbooks:
- Pagination (über Komponente)
- Captcha (über Komponente)
Schritt 1: SQL erzeugen
Anmerkung: Ich verwende hier den Namen tutorial_guestbook_entries as Tabellenname
Am Anfang steht immer die SQL Tabelle, bei der man sich am besten vorher überlegt, was überhaupt das Guestbook ausmachen soll. Ich habe mich wiefolgt entschieden:
- author (varchar(255)): Der Autor des Guestbook Eintrags
- email (varchar(255)): Eine gültige E-Mail Adresse
- entry (text): Der eigentliche Guestbook Eintrag
- created (datetime): Ein Cakeinternes Feld, das mit dem aktuellen DateTime Value (Format YYYY-MM-DD HH:II:SS) bestückt wird, sobald ein neuer Eintrag gespeichert wird
- modified (datetime): Ein Cakeinternes datetime Feld, das bei Updates der Tabellenzeile mit dem aktuellen Datum bestückt wird
Natürlich ist das Guestbook beliebig erweiterbar, diese Felder stellen das minimum dar, was zum Funktionieren nötig ist, bzw was zur Erklärung des Tutorials wichtig ist.
Fügt folgenden SQL Code in eure Datenbank ein:
-
CREATE TABLE tutorial_guestbook_entries (
-
id int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
-
author varchar(255) DEFAULT NULL,
-
email varchar(255) DEFAULT NULL,
-
entry text ,
-
created datetime DEFAULT NULL,
-
modified datetime DEFAULT NULL,
-
PRIMARY KEY (id)
-
) ENGINE=MyISAM;
Und nun noch ein paar Testeinträge
-
INSERT INTO `tutorial_guestbook_entries` VALUES (1, ‘Hans Mustermann’, ‘test@example.com’, ‘Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam ‘, ‘2007-05-24 09:35:36′, ‘2007-05-24 09:35:36′);
-
INSERT INTO `tutorial_guestbook_entries` VALUES (2, ‘Helmut Mustermann’, ‘test@example.com’, ‘Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam ‘, ‘2007-05-24 09:35:36′, ‘2007-05-24 09:35:36′);
-
INSERT INTO `tutorial_guestbook_entries` VALUES (3, ‘Horst Mustermann’, ‘test@example.com’, ‘Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam ‘, ‘2007-05-24 09:35:36′, ‘2007-05-24 09:35:36′);
Schritt 2: Model erzeugen
Nachdem wir festgelegt haben, welche Felder unsere Datenbank hat, wird es Zeit, die Verbindug zur Tabelle herzustellen. Dies geschieht über das Model.
Wir erstellen eine leere PHP Datei im Unterverzeichnis [root]/[app]/models/ mit Namen guestbook_entry.php. Hier finden wir auch zum ersten mal die Cake Conventions. Heisst die DB-Tabelle guestbook_entries, so nennt man das Model guestbook_entry (also der Singular). Weitere Informationen über Cake Conventions gibt es hier
Wir füttern nun unsere Datei mit folgendem Code:
[root]/[app]/models/guestbook_entry.php
-
<?php
-
class GuestbookEntry extends AppModel {
-
-
var $name = ‘GuestbookEntry’;
-
‘author’ => VALID_NOT_EMPTY,
-
‘email’ => VALID_EMAIL,
-
‘entry’ => VALID_NOT_EMPTY,
-
);
-
}
-
?>
Hiermit wird ein Bezug zur DB-Tabelle hergestellt. Was es mit dem $validate-Array auf sich hat, erfahrt Ihr später
Schritt 3: Controller erzeugen
Der Controller ist die Exekutive des MVC-Prinzips. Hier werden alle logischen Operationen vorgenommen.
Im Controller stellt jede Funktion eine Seite dar, das bedeutet, die Funktion view() würde über [root]/[app]/guestbook_entries/view aufgerufen. Die Cake Conventions besagen, dass Controller immer im Plural stehen, also heißt unser Controller in diesem Fall guestbook_entries_controller.php
Der Code für unsere Controller Datei lautet wie folgt:
[root]/[app]/controllers/guestbook_entries_controller.php
-
<?php
-
class GuestbookEntriesController extends AppController {
-
-
var $name = ‘GuestbookEntries’;
-
-
function index() {
-
$this->pageTitle = “Gästebuch”;
-
$criteria=NULL;
-
$this->set(‘guestbookEntries’, $this->GuestbookEntry->findAll($criteria,NULL,“GuestbookEntry.created DESC”, $limit, $page));
-
}
-
function captcha()
-
{
-
$this->Captcha->render();
-
}
-
-
function add() {
-
$this->pageTitle = “Gästebuch -> hinzufügen”;
-
-
} else {
-
$captcha = $this->Session->read(“captcha”);
-
if ($captcha == $this->data[‘GuestbookEntry’][‘captcha’])
-
if($this->GuestbookEntry->save($this->data)) {
-
$this->Session->setFlash(‘The Guestbook Entry has been saved’);
-
$this->redirect(‘/guestbook_entries/index’);
-
} else {
-
$this->Session->setFlash(‘Please correct errors below.’);
-
}
-
}
-
}
-
?>
Hier dürfte nun einiges an Klärungsbedarf bestehen.
Helpers: Unter var $helpers = … findet ihr die benötigten Helperklassen. Hier werden zwei Helperklassen benötigt. Meine Deutsch-Helper Class findet ihr hier im Blog, Pagination wird sehr gut in der CakePHP Bakery erklärt
Komponenten: Die Captcha Komponente findet ihr gut beschrieben auch wieder in der CakePHP Bakery.
Funktion Index
Hier listen wir die neusten Gästebucheinträge auf, dies wird die Hauptseite des Scripts. Sie ist unter [root]/guestbook_entries/ zu erreichen.
In der ersten Zeile finden wir
-
$this->pageTitle = “Gästebuch”;
dies ist wichtig für den Seitentitel, da dieser auf deutschen Seite doch meistens auch Deutsch sein sollte.
Die nächsten Zeilen ist vor allem für die Pagination wichtig, da dort die Pagination initiiert wird. In der letzten Zeile der index Funktion steckt die Magie.
Durch
-
$this->set(‘guestbookEntries’, $this->GuestbookEntry->findAll(…));
wird die komplette DB-Tabelle abegfragt und dem View mit der Variable $guestbookEntries übergeben. Da wir nur die neusten Einträge möchten, sortieren wir die Tabelle im 3. Feld von findall() mit created DESC, die anderen Einträge werden vom Paginationselement gemacht.
Die Captcha Funktion ist für das Captcha nachher wichtig, hiermit wird es initiiert.
Die Add Funktion ist für die Verarbeitung der Eingaben wichtig.
Hier haben wir auch wieder einen aussagekräftigen Pagetitle hinzugefügt. Danach wird abgefragt, ob vom Formular aus Daten geschickt wurden, in diesem Fall befindet sich der Inhalt als Array in $this->data. Ist dies nicht der Fall, wird das Add-Formular angezeigt.
Ist ein Eintrag vorhanden, so wird zunächst geprüft, ob das Captcha stimmt. Ist dies korrekt, werden Autor und Eintrag von möglichem Schadcode bereinigt (dafür gibt es auch eine Cake Lösung, die ich in einem späteren Tutorial vorstellen werde).
Nun wird versucht, die Daten zu speichern. Hier rufen wir uns nochmal unser Model ins Gedächtnis:
-
<?php $pagination->setPaging($paging); ?>
-
<div class=“guestbookEntries”>
-
<h2>Guestbook</h2>
-
<h3>Spammers will be shot!</h3>
-
-
<ul class=“actions”>
-
</ul>
-
-
-
<?php
-
echo $this->renderElement(’pagination’);
-
$i=0;?>
-
<table cellpadding=“0″ cellspacing=“0″ class=“gbook_table”>
-
<?php foreach ($guestbookEntries as $guestbookEntry):
-
$gbook = ($i++%2 == 0) ? “gbook_class1″ : “gbook_class2″;
-
?>
-
-
<tr class=“<?php echo $gbook;?>">
-
<td rowspan=”1” class=”gbook_number“><?php echo $guestbookEntry[’GuestbookEntry’][’id’]; ?></td>
-
<td colspan=”1“><?php echo $guestbookEntry[’GuestbookEntry’][’author’]; ?> schrieb am <?php echo $deutsch->de_date($guestbookEntry[’GuestbookEntry’][’created’],2); ?> </td>
-
</tr>
-
<tr class=”<?php echo $gbook;?>">
-
<?php endforeach; ?>
-
</table>
-
<? echo $this->renderElement(’pagination’);?>
-
</div>
Dies ist die Index Ausgabe, passend zur index Funktion im Controller. Beachtet, dass View Dateien immer .thtml oder .tpl als Endung besitzen. Dies kann etwas tricky sein, da ihr eventuell eurem Editor beibringen müsst, diese Dateien als php Dateien zu behandeln.
Schauen wir uns die Index Datei nun etwas genauer an. Am Anfang wird die Pagination gestartet, die am Ende der Datei das Element pagination steuert.
Richtig interessant wird der Code in der foreach Schleife. Wir können auf die im Controller definierte Variable (Ihr erinnert euch an $this->set(’guestbookEntries’,…)?) $guestbookEntries einfach im View zugreifen. Dieses Array wird nun durchlaufen. Der Arrayaufbau wurde durch Cake festgelegt und verhält sich wiefolgt:
-
(
-
(
-
(
-
[id] => 1
-
[author] => Hans Mustermann
-
[email] => test@example.com
-
[entry] => Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam
-
[created] => 2007-05-24 09:35:36
-
[modified] => 2007-05-24 09:35:36
-
)
-
-
)
-
-
(
-
(
-
[id] => 2
-
[author] => Helmut Mustermann
-
[email] => test@example.com
-
[entry] => Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam
-
[created] => 2007-05-24 09:35:36
-
[modified] => 2007-05-24 09:35:36
-
)
-
-
)
-
-
(
-
(
-
[id] => 3
-
[author] => Horst Mustermann
-
[email] => test@example.com
-
[entry] => Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam
-
[created] => 2007-05-24 09:35:36
-
[modified] => 2007-05-24 09:35:36
-
)
-
-
)
-
-
)
Durch diesen einfachen Arraycode ist es nun kein Problem, die einzelnen Punkte in einer Guestbook-Tabelle auszugeben.
Zur Übersichtlichkeit gibt es mit gbook_class1&2 zwei CSS Klassen, durch die man farblich die einzelnen Einträge unterscheiden kann. $deutsch->de_date() formatiert das Datum aus der DATETIME Variable nach deutscher Form. Hierzu verwende ich einen selbstgeschriebenen Helper, den ihr auch im Blog finden könnt.
Kommen wir nun zur letzten Datei, die da heißt:
[root]/[app]/views/guestbook_entries/add.thtml:
-
<h2>Guestbook</h2>
-
<h3>Eintrag vornehmen</h3>
-
-
<form action=“<?php echo $html->url(’/guestbook_entries/add’); ?>” method=“post”>
-
-
<p>Bitte einen Autor und einen Text eingeben. Danach noch das Captcha richtig schreiben und dein Eintrag wird gespeichert</p>
-
-
-
-
-
<p>Wenn du das Captcha nicht lesen kannst, lade die Seite neu, dein Text bleibt gespeichert. Glaube ich</p>
-
<p><img src=“<?php echo $html->url(’/guestbook_entries/captcha’); ?>” /><br>
-
-
<div class=“submit”>
-
</div>
-
</form>
-
<ul class=“actions”>
-
</ul>
Mittels dem html-Helper von Cake kann man Formulare einfach und Cake-kompatibel erstellen. Hier wird der Befehl $html->input verwendet, um Cake-konforme Input Felder zu generieren. Diese können dann im Controller über $this->data ausgelesen werden
Schlägt die Validierung im Controller fehl, so wird das Formular wieder angezeigt, alle Werte übernommen und bei dem Feld, dass den Fehler verursacht hat, die Ausgabe von tagErrorMsg ausgegeben.
Und nun heißt es: ausprobieren!
Für Feedback bin ich immer dankbar, auch wenn Fehler im Tutorial festgestellt werden sollten am besten sofort melden.
Veröffentlicht am Donnerstag, den 24. Mai 2007 um 10:07 Uhr veröffentlicht
Du kannst einen Kommentar schreiben, oder einen Trackback auf deiner Seite einrichten.
7 Reaktionen zu “CakePHP Tutorial 1: Guestbook Anwendung”
-
Am 24. Mai 2007 um 11:32 Uhr
Nette Einführung! Was mir allerdings immernoch schleierhaft ist und worüber ich auch in der cakePHP Googlegroup bislang noch keine Antwort bekam ist, wie man - wie in deinem Gästebuchscript - z.B. die Liste der Einträge und das Formular für neue Einträge gleichzeitig auf einer Seite darstellt und sämtliche Formularfehler auf diese Seite zurück gibt oder gar 2 Formulare auf einer Seite samt Fehlerüberprüfung darstellt …
Es wird immer auf die requestaction() Funktion hingewiesen, die aber für diesen Zweck (2 Formulare oder Pagination) nicht funktioniert, da der Controller der über diese Funktion aufgerufen wird, dann in einem anderen Kontext läuft und damit Validations nicht beim Controller verfügbar sind, der die requestaction macht.
Alle CakePHP Beispiele die ich bislang gesehen habe, haben immer eine Trennung von Ergebnislisten und Eingabe (wie auch hier beim Gästebuch, der offiziellen Anleitung, dem “Blog in 20 Minutes” Tutorial oder den Beispielen auf Developerworks von IBM.
In der “echten Welt” hat man aber halt meistens mehrere Funktionen auf einer Seite, die man aber von der Programmierung gerne so getrennt wie möglich haben möchte.
Ein Tipp aus der Community ist, alles als Plugin zu bauen, aber das kann es ja auch nicht sein.Eine Adminoberfläche, bei der man z.B. ein Beitragsformular, ein Formular in dem man eine neue Kategorie eintragen kann und eine Liste der vorhandenen Kategorien gleichzeitig hat, ist somit nicht so einfach zu realisieren.
Vielleicht hat ja jemand eine elegante Lösung parat?
Markus
-
Am 24. Mai 2007 um 12:00 Uhr
Ehrlich gesagt ist das Problem bei meinen Webseiten, die ich bisher mit Cake erstellt habe, nie aufgetreten.
Ich hole mir meistens einfach die Daten direkt für die Datei nochmals aus der DB, d.h. wenn ich eine Anzeige der letzten 5 Einträge haben möchte und danach das Add Formular, würde ich ein $this->set(”last_posts”, $this->GuestbookEntry->findAll(NULL,NULL, GuestbookEntry.created DESC, 0,5);
schreiben und dies dann auf der add.thtml ausgeben. Oder man könnte in der index Funktion ein return $guestbookEntries ausgeben (vorher natürlich die Variable mit Inhalt füllen) und dann $indexausgabe = requestAction(…) in dem gewünschten Controller schreiben. So kann man sich auch komplizierte Elemente aus anderen Controller nutzbar machen.Mehrere Formulare mit Validierung sind allerdings kein großes Problem. Dort einfach bei fehlgeschlagener Validierung ein $this->render(”name der ausgangsdatei”) ausgeben (bei mir im Beispiel hinter $this->Session->setFlash(”Please…);
Hoffe ich hab nicht zuviel Stuss geschrieben, ist gerade Mittagszeit

-
Am 15. September 2007 um 10:10 Uhr
Programming Tutorials…
I couldn’t understand some parts of this article, but it sounds interesting…
-
Am 17. Oktober 2007 um 11:10 Uhr
Gute Anleitung - aaaber:
Warum sind denn in dem Tutorial die Anführungszeichen so blöd eingebunden?
Ein simples Copy/Paste ist schlichtweg nicht möglich.
Warum? Weil aus jedem “ muss ich erstmal wieder ein ” oder ‘ machen.
Das ist doch Mist.
Ansonsten ist es natürlich ganz toll
-
Am 17. Oktober 2007 um 11:11 Uhr
ok. ich seh schon, das macht die anwendung selbst. dennoch ist das doch absolut bekloppt.
-
Am 17. Oktober 2007 um 11:12 Uhr
Ja, das ist leider noch ein Problem mit meinem Code-Viewer. Wenn du oder jemand anders ein tolles Code View Plugin für Wordpress kennt, übernehm ich das gerne.
-
Am 29. August 2008 um 08:25 Uhr
Ich finde den Aufbau der Seite sehr gut. Macht weiter so.
Auf einen Blick
Archiv
- Oktober 2008
- August 2008
- Juli 2008
- Juni 2008
- Mai 2008
- April 2008
- März 2008
- Februar 2008
- Januar 2008
- Dezember 2007
- November 2007
- Oktober 2007
- September 2007
- August 2007
- Juli 2007
- Juni 2007
- Mai 2007
- April 2007
Kategorien
- Allgemein (72)
- Cake vs Rails (3)
- CakePHP (42)
- Meinung (16)
- Projekt (6)
- Rails (5)
- Tipps (27)
- Typo3 (4)
Letzte Einträge:
- 11.04.2007: Neustart
- 11.04.2007: Design Version 1 steht
- 11.04.2007: Blog