CakePHP 1.2 Blog Tutorial Teil 4: mehr Gebäck!
Zuerst einmal vielen Dank für das Feedback auf meine ersten drei Blogartikel, freut mich, dass ihr den Artikel so wohlwollend aufgenommen habt. Wie ich schon angedeutet habe, wird der Dreiteiler natürlich nicht das Ende des Tutorials sein, denn in CakePHP gibt es noch viel mehr zu entdecken. Da ich leider jedoch auch noch für meine Brötchen arbeiten muss, wird es weitere Teile des Blog Tutorials immer mit etwas Abstand geben. Zudem arbeite ich gerade an der englischen Übersetzung, die hoffentlich bald auch veröffentlicht werden kann.
Bevor es zum Inhalt dieses Artikels kommt, noch etwas in eigener Sache: Falls jemand ein gutes Plugin kennt, um PHP Code mit Syntaxhighlighting inklusive Copy and Paste hier im Blog einzufügen, bitte mir den Link schicken. Das aktuelle Plugin ist zwar auch OK, aber es geht sicherlich noch besser.
Dieses Tutorial schließt an meine ersten drei Teile an. Wer bisher noch keinen Kontakt mit CakePHP hatte oder das Tutorial noch nicht durchgespielt hat, sollte dies zunächst tun. Für die ganz schnellen unter uns gibt es den Code zum Tutorial im dritten Teil zum Download, so dass ihr gleich loslegen könnt.
Inhaltsverzeichnis:
- Routes
- Layout verändern
- Kommentare hinzufügen
- Captcha Komponente erstellen
Teil 4: mehr Gebäck!
Teil 4.1
Routes
Nach dem Installieren des Tutorial Blogs werdet ihr sicher auch festgestellt haben, dass beim Aufruf von http://localhost/tutorial/ nicht unbedingt die Seite kommt, die ihr euch vorstellt, sondern die Cake Startseite. Erst beim Aufruf von http://localhost/tutorial/posts/ werdet ihr die korrekte Seite sehen. Dies ist ein Zustand, den man so guten Gewissens nicht lassen kann, denn wer will schon seinen Usern eine URL www.example.com/posts/ aufdrücken? Die User sollen nach dem Aufruf von www.example.com schließlich auf die richtige Seite umgeleitet werden.
Um diesem Problem Herr zu werden, verwendet Cake eine besondere Technik, die Routes. Diese liegen, wie der Name vermuten lässt, in der Datei Routes.php im /app/config/ Ordner.
In Zeile 36 dieser Datei sehen wir den folgenden Ausdruck:
/app/config/routes.php
Hier verweisen wir also bei Aufruf von “/” (also von http://localhost/tutorial/, dem Rootfolder von Cake) auf den Controller “Pages” und die Aktion “display”.
Wir ändern nun die Route wiefolgt ab:
/app/config/routes.php
Durch diese Änderung wird nun bei Aufruf von “/” auf “/posts/index” verwiesen, was in diesem Tutorial der Indexseite entspricht. Einfach, oder? Euch wird es sicherlich leicht fallen, weitere Routes anzulegen, um die Macht dieser kleinen Datei voll ausnutzen zu können.
Dazu noch ein Tipp:
Setzt ihr den mächtigen : Operator ein, so könnt ihr diesen via $this->params['group'] mit einem Wert belegen, zum Beispiel nur Posts aus einem bestimmten Thema anzeigen.
Teil 4.2
Layout
In den Kommentaren zu den ersten drei Tutorialteilen war auch ein Kommentar, wo gefragt wurde, wie man ein eigenes Layout erstellen kann. Dies will ich nun erklären.
Bisher ist unser Blog Tutorial noch sehr im offiziellen Cake Stil gehalten, was wenig verwunderlich ist, da wir das Layout und das CSS von Cake einsetzen. Um ein eigenes Layout zu erstellen, legt ihr im Ordner /app/views/layouts die Datei default.ctp an. Fügt nun folgenden Code in diese Datei ein:
/app/views/default.ctp
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
<html xmlns="http://www.w3.org/1999/xhtml">
-
<head>
-
<title><?php echo $title_for_layout;?></title>
-
</head>
-
<body>
-
<?php
-
$session->flash();
-
echo $content_for_layout;?>
-
</body>
-
</html>
Momentan noch sehr rudimentär erkennt ihr sicherlich trotzdem drei wesentliche Punkte. Das Title-Tag wird mit $title_for_layout gefüllt, was standardmäßig dem aktuellen Controller entspricht, in Fall eines Aufrufes von “http://localhost/tutorial/” sollte dies der Posts Controller sein.
Im Body sehen wir zwei Tags, zum einen $content_for_layout, das, wie erwartet, den Inhalt der Seite präsentiert, also den View, zum anderen $session->flash(). Diese Funktion ist für die Ausgabe der $this->Session->setFlash(‘Message’) Nachrichten, mit der man dem User mitteilen kann, ob seine gerade ausgeführte Aktion Erfolg hatte oder nicht. Beispiele findet ihr in der posts_controller.php Datei.
Wenn ihr nun die Seite aufruft, werdet ihr feststellen, dass vom ursprünglichen Layout nichtmehr viel übrig geblieben ist. Um eine CSS Datei zu laden, fügt folgenden Code hin den Header der default.ctp ein:
/app/views/default.ctp
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
<html xmlns="http://www.w3.org/1999/xhtml">
-
<head>
-
<title><?php echo $title_for_layout;?></title>
-
<?php echo $html->css("cake.generic");?>
-
</head>
-
<body>
-
<div id="content">
-
<?php
-
$session->flash();
-
echo $content_for_layout;?>
-
</div>
-
</body>
-
</html>
Nach einem Refresh eurer Seite sehr ihr nun wieder das Cake Türkisgrün, allerdings nun etwas leichtgewichtiger, da wir ja keinen Header mehr haben ![]()
Damit die ganze Seite aber nun zumindest etwas mehr wie ein Blog, und weniger wie die Scaffoldseite aussieht, legen wir noch etwas Hand an.
Erstellt zuerst folgende CSS Datei:
/app/webroot/css/blog.css
-
.post {
-
width: 600px;
-
margin: 20px;
-
}
-
-
.small {
-
font-size: 80%;
-
}
Damit diese CSS Datei auch geladen wird, schreiben wir sie nun in den Header des Layouts:
/app/views/layouts/default.ctp
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
<html xmlns="http://www.w3.org/1999/xhtml">
-
<head>
-
<title><?php echo $title_for_layout;?></title>
-
<?php echo $html->css("cake.generic");?>
-
<?php echo $html->css("blog");?>
-
</head>
-
<body>
-
<div id="content">
-
<?php
-
$session->flash();
-
echo $content_for_layout;?>
-
</div>
-
</body>
-
</html>
Nun ändert noch die Posts/Index Datei ab:
/app/views/posts/index.ctp
-
<h1>Mein erstes Blog</h1>
-
<?php echo $html->link(‘Neuer Beitrag’, ‘/posts/add’);?>
-
-
<?php foreach($posts as $post):?>
-
<div class="post">
-
<h1><?php echo $html->link($post[‘Post’][‘titel’], "/posts/view/".$post[‘Post’][‘id’]);?></h1>
-
<p class="small">Erstellt am <?php echo $datum->date_de($post[‘Post’][‘created’], 2);?></p>
-
<p><?php echo $post[‘Post’][‘inhalt’];?></p>
-
<p class="small"><?php echo $html->link(‘(‘.count($post[‘Comment’]).‘) Kommentare’, "/posts/view/".$post[‘Post’][‘id’]."#comments");?> <?php echo $html->link(‘Editieren’, ‘/posts/edit/’.$post[‘Post’][‘id’]);?> <?php echo $html->link(‘Löschen’, ‘/posts/delete/’.$post[‘Post’][‘id’], null, ‘Wirklich löschen?’);?></p>
-
</div>
-
<?php endforeach;?>
Dies ist zwar noch nicht der Weisheit letzter Schluss, aber es kommt schon eher an den Namen “Blog” heran. Zudem haben wir gleich noch die geschriebenen Kommentare gezählt.
Ihr könnt nun eure Seite selbst stylen, wie ihr möchtet, euch sind dank CSS keine Grenzen gesetzt. Wenn ihr Inspiration sucht, geht doch mal in den www.csszengarden.com. Dort werdet ihr mit Sicherheit erleuchtet.
Teil 4.3
Kommentar hinzufügen
Dieses Thema hatten wir schon im dritten Teil des Tutorials, aber auf vielfachen Wunsch und zur Vorbereitung der nächsten Lektion fügen wir nun eine Möglichkeit ein, wie ein User einen Kommentar in unserem Blog hinterlassen kann.
Dazu editieren wir die Datei /app/views/posts/view.ctp und fügen ein Formular ein, mit dem User Kommentare direkt abgeben können.
/app/views/posts/view.ctp
-
<h1><?php echo $post[‘Post’][‘titel’];?></h1>
-
<p><?php echo $post[‘Post’][‘inhalt’];?></p>
-
<p>Dieser Beitrag wurde erstellt am: <?php echo $datum->date_de($post[‘Post’][‘created’]);?></p>
-
<p><?php echo $html->link(‘zurück zur Übersicht’, ‘/posts/’);?></p>
-
-
<h2>Kommentare:</h2>
-
<?php foreach($post[‘Comment’] as $comment):?>
-
<p><?php echo $comment[‘autor’];?> schrieb am <?php echo $datum->date_de($comment[‘created’],2);?>:</p>
-
<p><?php echo $comment[‘inhalt’];?></p>
-
<hr>
-
<?php endforeach;?>
-
<!– NEU –>
-
<h2>Kommentar verfassen</h2>
-
<?php echo $form->input(‘autor’);?>
-
<?php echo $form->input(‘inhalt’);?>
-
<?php echo $form->submit(‘Kommentar senden’);?>
-
<?php echo $form->end();?>
-
<!– ENDE –>
Ein weiterer Vorteil der CakePHP Formulare ist die Magie des $form->input Elements. Es kann anhand des Datenbankfeldes erkennen, welcher Typ am besten für das Element geeignet ist. In diesem Fall bekommen wir für das Feld “Inhalt” automatisch ein Textfield angezeigt.
Tipp: Verwendet, wann immer ihr könnt, das $form->input Element. Dort sind mit Abstand die meisten Optionen vorhanden, es erstellt standardmäßig Divs und Labels und und und. Wollt ihr einen Typ definieren, schreibt einfach:
Ersetzt den Type durch den Feldtyp, den ihr haben möchtet, in diesem Fall wird es ein Datum.
Damit das Kommentar auch gespeichert wird, fehlt uns noch folgende Add-Funktion:
/app/controllers/comments_controller.php
-
<?php
-
-
class CommentsController extends AppController
-
{
-
var $name = ‘Comments’;
-
var $scaffold;
-
-
function add($id = NULL) {
-
$this->data[‘Comment’][‘post_id’] = $id;
-
$this->data[‘Comment’][‘id’] = ”;
-
if ($this->Comment->save($this->data)) {
-
$this->Session->setFlash(‘Kommentar hinzugefügt’);
-
$this->redirect($this->referer());
-
}
-
}
-
}
-
}
-
-
?>
Nun sollte es möglich sein, Kommentare auch direkt im Artikel zu schreiben. Allerdings gibt es in der heutigen Internetzeit das Problem, dass viele Spammer gerne auf Blogs losgehen. Ohne Absicherung ist man nicht mehr sicher. Genau darum kümmern wir uns jetzt und lernen nebenbei das Anlegen einer Komponente.
Teil 4.3
Captcha Komponente erstellen
Zuerst einmal die Vorüberlegung. Unser Captcha soll zugänglicher sein als die Grafikcaptchas, gleichzeitig aber relativ sicher, zumindest solange sich niemand die Mühe macht und das Script aushebelt. Bei unserer kleinen Seite sollte also ein kleines Script ausreichen.
Damit der User ein Kommentar abgeben kann, muss er etwas kopfrechnen, und zwar stellen wir ihm Aufgaben wie “drei Kuchen plus ein Kuchen”. Wenn er nun 4 in das Captchafeld eingibt, wird das Kommentar gespeichert, sonst nicht. Ich muss zugeben, dass diese Idee nicht von mir ist, sondern bereits in vielen Blogs Verwendung findet, allerdings geht es hier auch nicht um Innovation, sondern um Cake, oder?
Erstellen wir zunächst die Komponente. Komponenten befinden sich im Ordner /app/controller/components und können sowohl vom View wie auch vom Controller angesprochen werden. Dieses Verhalten machen wir uns zunutze:
/app/controllers/components/dievocap.php
-
<?php
-
class DievocapComponent extends Object
-
{
-
function startup(&$controller)
-
{
-
$this->controller = $controller;
-
}
-
-
function render()
-
{
-
$summe = $zahl1 + $zahl2;
-
$this->controller->Session->write("dievocaptcha.ergebnis",$summe);
-
$this->controller->Session->write("dievocaptcha.zahl1",$zahlen[$zahl1]." Kuchen ");
-
$this->controller->Session->write("dievocaptcha.zahl2",$zahlen[$zahl2]." Kuchen ");
-
}
-
}
-
?>
Zur Funktion:
in der Funktion “startup” wird zunächst festgelegt, dass die Komponente mithilfe von “controller” jeden beliebigen Controller imitieren kann. Dadurch kann die nächste Funktion erst erfolgreich sein.
In der Render Funktion wird zunächst das Array mit den ausgeschrieben Zahlen gefüllt. Danach werden zufällig zwei Zahlen ausgewählt und addiert. Ist dies geschehen, schreiben wir sowohl die beiden Zahlen wie auch das Ergebnis in die aktuelle Session.
Nun geht es an den View. Damit das Captcha auch korrekt angezeigt wird, erweitern wir unseren View wie folgt:
/app/views/posts/view.ctp
-
<h1><?php echo $post[‘Post’][‘titel’];?></h1>
-
<p><?php echo $post[‘Post’][‘inhalt’];?></p>
-
<p>Dieser Beitrag wurde erstellt am: <?php echo $datum->date_de($post[‘Post’][‘created’]);?></p>
-
<p><?php echo $html->link(‘zurück zur Übersicht’, ‘/posts/’);?></p>
-
-
<h2>Kommentare:</h2>
-
<?php foreach($post[‘Comment’] as $comment):?>
-
<p><?php echo $comment[‘autor’];?> schrieb am <?php echo $datum->date_de($comment[‘created’],2);?>:</p>
-
<p><?php echo $comment[‘inhalt’];?></p>
-
<hr>
-
<?php endforeach;?>
-
<h2>Kommentar verfassen</h2>
-
<?php echo $form->input(‘Autor’);?>
-
<?php echo $form->input(‘inhalt’);?>
-
<!– NEU –>
-
<div class="input">
-
<p>Löse die folgende Aufgabe, um deinen Eintrag absenden zu können:</p>
-
<p>Summe aus <?php echo $session->read("dievocaptcha.zahl1")." und ".$session->read("dievocaptcha.zahl2");?> ist
-
<?php echo $form->input("captcha", array(‘style’ => ‘width: 40px’, ‘div’=>false, ‘label’=>false));?></p>
-
</div>
-
<!– ENDE –>
-
<?php echo $form->submit(‘Kommentar senden’);?>
-
<?php echo $form->end();?>
Bisher wird es aber so noch nicht funktionieren, da ein elementarer Teil fehlt: Der Controller muss natürlich auch noch erweitert werden, und zwar so:
/app/controllers/posts_controller.php (Auszug)
-
<?php
-
class PostsController extends AppController
-
{
-
var $name = ‘Posts’;
-
-
function index() {
-
$eintraege = $this->Post->findAll();
-
-
$this->set(‘posts’,$eintraege);
-
}
-
-
-
function view($id = NULL) {
-
$this->Post->id = $id;
-
$this->set(‘post’,$this->Post->read());
-
$this->Dievocap->render();
-
}
-
[…]
-
?>
Passt hierbei auf, dass wir dies in den Posts Controller schreiben, nicht in den Comments Controller.
Mit var $components = array(‘Dievocap’); laden wir zuerst die Komponente. Dann setzen wir im View den Befehl $this->Dievocap->render();, um das Captcha zu initialisieren. Wenn ihr nun die Seite ladet, seht ihr bereits das Captcha arbeiten. Allerdings müssen wir das Ergebnis noch prüfen. Dies erledigen wir im Comments_Controller:
/app/controllers/comments_controller.php
-
<?php
-
-
class CommentsController extends AppController
-
{
-
var $name = ‘Comments’;
-
var $scaffold;
-
-
function add($id = NULL) {
-
if (!empty($this->data) && ($this->Session->read(‘dievocaptcha.ergebnis’) == $this->data[‘Comment’][‘captcha’])) {
-
$this->data[‘Comment’][‘post_id’] = $id;
-
$this->data[‘Comment’][‘id’] = ”;
-
if ($this->Comment->save($this->data)) {
-
$this->Session->setFlash(‘Kommentar hinzugefügt’);
-
$this->redirect($this->referer());
-
}
-
} else {
-
$this->Session->setFlash(‘Fehler: bitte Eingabe überprüfen’);
-
$this->redirect($this->referer());
-
}
-
}
-
}
-
-
?>
Nachdem dies geschehen ist, sollte das Captcha funktionieren. Damit habt ihr nun gelernt, wie man Komponenten erstellt, ist dieser Teil des Tutorials beendet. Wenn es euch gefallen hat, hinterlasst doch einen Kommentar, wenn ihr Fehler entdeckt habt, teilt sie mir bitte mit, damit ich sie korrigieren kann. Habt ihr weitere Fragen, oder wünscht ihr mehr Tutorials? Teilt mir eure Wünsche mit, damit ich die Tutorialserie fortsetzen kann.
Zu guter Letzt gibt es natürlich auch diesmal wieder das Tutorial als Download, inklusive der SQL DB.
Kategorie: CakePHP, Tipps | 37 Kommentare »
Veröffentlicht am Freitag, den 19. Oktober 2007 um 08:53 Uhr veröffentlicht
Du kannst einen Kommentar schreiben, oder einen Trackback auf deiner Seite einrichten.
