CakePHP & DIEVOLUTION Blog
CakePHP 1.2 Blog Tutorial Teil 2
Im zweiten Teil unseres Tutorials behandeln wir das Tutorial an sich.
2. Tutorial
- Vorüberlegungen
- Datenbank einrichten und Daten einfügen
- Models: Datenbank abfragen
- Controller: Logik erschaffen
- Views: Ausgabe erstellen
- Posts hinzufügen und Datenvalidierung
- Posts löschen und editieren
Teil 2.1:
Vorüberlegungen
Wie soll unser Blog aussehen. Da natürlich in jedem Tutorial nur begrenze Resourcen zur Verfügung stehen und CakePHP so viele Möglichkeiten bietet, halte ich mich ein wenig an das offizielle Blogtutorial der 1.1er Version und verzichte hier auf die Erstellung von Dateien mittels bake. Heute backen wir einmal von Hand.
Unsere Ziele für unser Blog:
- Eintragen, Editieren und Löschen von Beiträgen
- Möglichkeit zum Kommentieren von Beiträgen
Weitere Extras werden wir dann zum Schluss in Teil drei des Tutorials hinzufügen.
Teil 2.2:
Datenbank einrichten und Daten einfügen
Zuerst sollten wir eine Datenbank erstellen. Dazu erstellt ihr beispielsweise per PHPmyAdmin eine Datenbank, nennt sie ‘cake_tutorial’. Danach geht ihr in den Ordner /tutorial/app/config/ und erstellt eine Kopie der Datei database.php.default, nennt sie database.php. Nun öffnet ihr die Datei und ändert sie auf folgende Einstellungen:
-
‘driver’ => ‘mysql’,
-
‘persistent’ => false,
-
‘host’ => ‘localhost’, /* bzw. euer Datenbankhost */
-
‘login’ => ‘root’, /* Euer Login Name der DB*/
-
‘password’ => ‘password’, /* Euer DB Passwort */
-
‘database’ => ‘cake_tutorial’,
-
‘prefix’ => ‘cake_’ /* Siehe unten */
-
);
Wenn ihr bei eurem Hosten z.B. nur eine Datenbank zur Verfügung habt, könnt ihr mittels ‘prefix’ ein Präfix für alle Datenbanktabellen verwenden, die erstellt werden. Dies wäre zum Beispiel cake_posts anstatt posts. Tragt dafür in das ‘prefix’ Feld “cake_” ein. Das Präfix hat keinerlei Auswirkungen auf die anderen Namen des MVC, nur die Tabelle der Datenbank muss natürlich dann angepasst werden. Ich verwende hier ein Präfix, es sieht einfach ordentlicher aus
Habt ihr die Datei geändert und abgespeichert, öffnet euren Browser und geht auf das Root-Verzeichnis euer Cake Installation, hier wäre das “/tutorial/”.
Ihr solltet nun die Cake Standardseite sehen, wichtig sind die beiden Zeilen Your database configuration file is present. und Cake is able to connect to the database.. Dies bedeutet, Cake kann zur Datenbank verbinden. Sollte dies bei euch nicht stehen, kontrolliert bitte nochmals die Schritte und eure Datenbankverbindung.
Wie ihr vielleicht bemerkt habt, haben wir eine “Notice”, die uns anweist, den CAKE_SESSION_STRING Salt zu ändern. (Notice: Please change the value of CAKE_SESSION_STRING in app/config/core.php to a salt value specific to your application in…) Dies ist eine Sicherheitsmaßnahme, die wir natürlich gerne schnell umsetzen. Geht dafür in die Datei /tutorial/app/config/core.php und ändert in der Zeile 97 den entsprechenden Wert ab. Eure Sessions sollten nun sicherer sein.
Was nun natürlich noch fehlt, sind Testdaten, mit denen wir arbeiten können. Und eine Datenbank haben wir auch noch nicht, lasst uns das ändern!
Öffnet wieder die Datenbankadministration eures Vertrauens (bei mir ist das immernoch PHPmyAdmin) und fügt in der angelegten Datenbank folgenden SQL Befehl ein:
-
CREATE TABLE cake_posts (
-
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
-
titel VARCHAR(50),
-
inhalt TEXT,
-
created DATETIME DEFAULT NULL,
-
modified DATETIME DEFAULT NULL
-
);
Eine ID wird bei jeder Tabelle benötigt. Die Tabellenfelder titel und inhalt dienen für die einzelnen Beiträge, die Felder created und modified werden von Cake automatisch mit dem passenden Wert gefüllt. Dazu später mehr.
Nun folgen noch ein paar Testdatensätze:
-
INSERT INTO cake_posts (titel,inhalt,created)
-
VALUES (‘Ein Titel’, ‘und ein Inhalt’, NOW());
-
INSERT INTO cake_posts (titel,inhalt,created)
-
VALUES (‘Ein weiterer Titel’, ‘Und der Beitragsinhalt folgt sogleich’, NOW());
-
INSERT INTO cake_posts (titel,inhalt,created)
-
VALUES (‘Schon wieder ein Titel’, ‘Hier fehlt der Witz des englischen Orginalbeitrages, denn NOT! Witze kommen im Deutschen einfach nicht so gut an.’, NOW());
Ist dies geschafft, geht es nun ans Eingemachte!
Teil 2.3:
Models: Datenbank abfragen
Wie ihr euch sicher erinnert, werden Models bei CakePHP in der Einzahl angegeben. Deshalb erstellen wir in dem Ordner /app/models/ die Datei post.php mit folgendem Inhalt:
/app/models/post.php
-
<?php
-
-
class Post extends AppModel
-
{
-
var $name = ‘Post’;
-
}
-
-
?>
Das wars auch schon mit dem Model. Es sucht nun automatisch die passende Datenbanktabelle, in unserem Fall cake_posts. Kommen wir zum nächsten Schritt.
Teil 2.4:
Controller: Logik erschaffen
Ein Model ist zwar schön, aber ohne Fotograf wird es nie groß rauskommen. Dies ist bei unserem Model ähnlich, allerdings braucht es hier keine Kamera, sondern eine Controllerdatei. Wir erstellen folgende Datei:
/app/controller/posts_controller.php
-
<?php
-
-
class PostsController extends AppController
-
{
-
var $name = ‘Posts’;
-
}
-
-
?>
Jetzt haben wir einen Controller, den wir über www.example.com/posts aufrufen könnten. Dies leitet die Anfrage auf die Aktion “index” um, also dasselbe wie www.example.com/posts/index.
Nur haben wir noch keine Index Aktion. Bevor wir nun allerdings die Aktion hinzufügen, ruft doch mal im Browser die URL www.euredomain.com/posts auf. Wir erhalten nun eine Fehlerseite, die uns aber gleich mit einem Code versorgt, der uns weiterhilft. So ist Cake eben. Also fügen wir folgenden Code zu unserem Posts Controller hinzu:
/app/controller/posts_controller.php
-
<?php
-
-
class PostsController extends AppController
-
{
-
var $name = ‘Posts’;
-
-
/*NEU*/
-
function index() {
-
}
-
/*ENDE*/
-
}
-
-
?>
Ruft jetzt nochmals die URL auf. Nun hat sich der Fehler geändert, wir haben keinen View! Das ist etwas, was wir gleich beheben wollen, zuerst braucht unsere Index Aktion aber noch ein wenig mehr Action. Fügt also folgenden Code hinzu:
/app/controller/posts_controller.php
-
<?php
-
-
class PostsController extends AppController
-
{
-
var $name = ‘Posts’;
-
-
-
function index() {
-
/*NEU*/
-
$eintraege = $this->Post->findAll();
-
-
$this->set(‘posts’,$eintraege);
-
/*ENDE*/
-
}
-
-
}
-
-
?>
Wir haben nun Bewegung in unseren Controller gebracht. Cake wird mit diesem Code versuchen, das Model Post anzusprechen ($this->Post) und in der dazugehörenden Datenbanktabelle alle Einträge zu finden ($this->Post->findAll()). Diese Daten werden als Array in der Variable $eintraege gespeichert. Um die Daten nun in der Ausgabe, dem View, verwenden zu können, verwenden wir die Funktion set. Mittels $this->set(’posts’,$eintraege) legen wir fest, dass die Variable $posts im View mit dem Inhalt der Variable $eintraege belegt werden soll. Durch dieses Konzept stören die Variablen sich nicht gegenseitig. Man kann diese Aktion auch einzeilig schreiben:
-
$this->set(‘posts’,$this->Post->findAll());
Teil 2.5:
Views: Ausgabe erstellen
Damit wir die Früchte unserer Arbeit auch ernten können, benötigen wir natürlich noch eine Ausgabe. Hierzu gehen wir in den Ordner /app/views/ und erstellen dort einen neuen Ordner “posts”. Hier wird auch wieder eine Konvention deutlich, Viewsordner sind klein und im Plural des Models geschrieben. Einfach, oder?
Achtung Umsteiger: Ab CakePHP 1.2 werden Views nichtmehr mit der Endung .thtml sondern mit der Endung .ctp versehen.
Tipp:Möchtet ihr einen View erstellen, der keine Logik oder Datenbankanbindung benötigt (beispielsweise ein Impressum) so erstellt ihn im Ordner “pages”. An diese Dateien kommt ihr dann über www.example.com/pages/dateiname_ohne_ctp. So müsst ihr nicht unnötigen Code generieren.
Wir erstellen also den Ordner posts und darin die Datei index.ctp:
/app/views/posts/index.ctp
-
<h1>Mein erstes Blog</h1>
-
<?php debug($posts);?>
An dieser Stelle lassen wir uns zunächst über die DEBUG Funktion den Inhalt des Arrays ausgeben. Ruft einfach wieder im Browser die /posts/ auf.
Inhalte von $posts
-
(
-
(
-
(
-
[id] => 1
-
[titel] => Ein Titel
-
[inhalt] => und ein Inhalt
-
[created] => 2007-10-01 22:12:20
-
[modified] =>
-
)
-
-
)
-
-
(
-
(
-
[id] => 2
-
[titel] => Ein weiterer Titel
-
[inhalt] => Und der Beitragsinhalt folgt sogleich
-
[created] => 2007-10-01 22:12:20
-
[modified] =>
-
)
-
-
)
-
-
(
-
(
-
[id] => 3
-
[titel] => Schon wieder ein Titel
-
[inhalt] => Hier fehlt der Witz des englischen Orginalbeitrages, denn NOT! Witze kommen im Deutschen einfach nicht so gut an.
-
[created] => 2007-10-01 22:12:20
-
[modified] =>
-
)
-
-
)
-
-
)
So sollte nun eure Ausgabe aussehen (in einem schönen… gelben Kasten). Dieses Array können wir im View nun wunderbar ausgeben. Ersetzt die Debug Zeile nun durch diesen Code:
/app/views/posts/index.ctp
-
<h1>Mein erstes Blog</h1>
-
<table>
-
<tr>
-
<th>Titel</th>
-
<th>Inhalt</th>
-
<th>Erstellt</th>
-
</tr>
-
<?php foreach($posts as $post):?>
-
<tr>
-
</tr>
-
<?php endforeach;?>
-
</table>
Das sieht doch schon super aus, oder? Mit einfachsten Mitteln haben wir eine schöne Ausgabe erstellt. Außerdem haben wir hier auch unseren ersten Helper verwendet. Helper sind kleine Scripte, die in Views verschiedene Ausgaben erstellen, in diesem Fall haben wir einen Link erstellt, der unseren Titel auf die Url www.example.com/posts/view/id_des_eintrags verweist. Kurze URLs sind ein weiterer Vorteil von Cake, normalerweise sind sie immer im Format /controller/action/id/weitere/argumente.
Noch fehlt uns aber die Aktion “view” im Controller, daher erstellen wir diese nun:
/app/controller/posts_controller.php
-
<?php
-
-
class PostsController extends AppController
-
{
-
var $name = ‘Posts’;
-
-
-
function index() {
-
$eintraege = $this->Post->findAll();
-
-
$this->set(‘posts’,$eintraege);
-
}
-
-
/*NEU*/
-
function view($id = NULL) {
-
$this->Post->id = $id;
-
$this->set(‘post’,$this->Post->read());
-
}
-
/*ENDE*/
-
}
-
-
?>
Hier fällt auf, dass wir nicht mit der Find-Funktion, sondern mit read arbeiten. Dies bietet sich immer dann an, wenn wir nur einen Datensatz benötigen. Wollen wir einen Datensatz finden, bei dem uns aber zum Beispiel nur der Name bekannt ist, können wir die magische findBy Funktion verwenden. Das könnte dann so aussehen:
-
$this->Post->findByTitel(‘Gesuchter Titel’);
Dies gibt uns den ersten Datensatz mit dem Titel “Gesuchter Titel” zurück, falls vorhanden. In Cake gibt es sehr viele nützliche Funktionen, schaut mal auf api.cakephp.org, wenn ihr genaueres erfahren wollt. Nun haben wir also unsere view-Action, aber noch keinen View.
Daher erstellen wir noch schnell einen kleinen View, damit wir die Früchte unserer Arbeit ernten beziehungsweise die Ausgabe unseres Views sehen können.
/app/views/posts/view.ctp
Wie ihr vielleicht bemerkt habt, befindet sich das “created” Feld noch in der SQL Datumsanzeige, die für den Europäer etwas befremdlich zu lesen ist. Obwohl in Cake 1.2 alles schon ein wenig einfacher geworden ist, sind diese Daten noch am besten mit einem kleinen Helfer umzuschreiben. Wie das geht, erfahrt ihr später (ja, manchmal spann ich die Leute gern auf die Folter).
Nun wissen wir also, wie einfach es ist, Listen und Posts mit CakePHP anzuzeigen. Aber brennt ihr nicht auch darauf, selbst Beiträge zu erstellen? Dann nichts wie auf ins nächste Kapitel!
Teil 2.6:
Posts hinzufügen und Datenvalidierung
Zuerst brauchen wir, wie immer, die passende Action im Controller, die uns die Möglichkeit gibt, Posts zu erstellen. Das ganze sieht so aus:
/app/controller/posts_controller.php
-
<?php
-
-
class PostsController extends AppController
-
{
-
var $name = ‘Posts’;
-
/*NEU*/
-
/*Ende*/
-
-
function index() {
-
$eintraege = $this->Post->findAll();
-
-
$this->set(‘posts’,$eintraege);
-
}
-
-
-
function view($id = NULL) {
-
$this->Post->id = $id;
-
$this->set(‘post’,$this->Post->read());
-
}
-
-
/*NEU*/
-
function add() {
-
if ($this->Post->save($this->data)) {
-
$this->Session->setFlash(‘Der Beitrag wurde erfolgreich gespeichert’);
-
$this->redirect(‘/posts’);
-
} else $this->Session->setFlash(‘Fehler’);
-
}
-
}
-
/*ENDE*/
-
}
-
-
?>
Huch ist das aber eine große Action, jedenfalls für Cake Verhältnisse. Gehen wir am besten Zeile für Zeile durch.
Beachtet zuerst die Zeile, die ganz oben neu eingefügt wurde. Damit laden wir Formular-Helper, der uns gleich gute Dienste leisten wird. Wenn ihr selbst Helper erstellt habt oder andere vorgefertige Helper nutzen wollt, hängt sie einfach in dem Array an, beispielsweise var $helpers = array(’Form’, ‘Ajax’, ‘Javascript’);. Uns genügt hier aber der Form-Helper.
Nach dem Aufruf der Action selbst wird abgefragt, ob sich im Formulardatenarray($this->data) Daten befinden. Dieses Array speichert alle Daten, die im View mit einem Formular abgeschickt wurden. Ist es nicht leer, versucht Cake in der nächsten Zeile mit dem Befehl save die Daten im Model Post, d.h. in der Datenbanktabelle cake_posts, zu speichern. War dies erfolgreich, so wird eine spezielle Nachricht gesetzt ($this->Session->setFlash) und dann auf die Index-Datei des Verzeichnisses verwiesen ($this->redirect).
Sollte es einen Fehler beim speichern gegeben haben, meldet Cake dies mit dem Wort “Fehler”. Cake versucht automatisch die eingegeben Daten zu validieren, gibt es eine Regelverletzung, schlägt der Savebefehl fehl. Dies probieren wir am besten gleich einmal aus, aber dafür brauchen wir erstmal den Add-View.
Achtung Umsteiger: In 1.2 wurden die Helperfunktionen komplett überarbeitet, das Beispiel aus dem 1.1er Blog Tutorial funktioniert jetzt nicht mehr.
/app/views/posts/add.ctp
Da besteht Erklärungsbedarf!
Zuerst erstellen wir mittels $form->create(’Post’) ein Formular-HTML-Tag. Diesem geben wir noch das dazugehörige ‘Post’ mit auf den Weg, so dass Cake weiß, zu welchem Teil der Anwendung es gehört. Durch diesen super Befehl können wir uns weiter viel Code sparen, denn nun müssen wir nur noch ein input Feld und eine textarea erzeugen, die jeweils die Namen der Datenbankfelder enthalten. Aus dem Form Tag und dem Namen des Felder erstellt Cake HTML Tags, die die Form “data[model][name]” besitzen, in diesem Fall beispielsweise data[post][titel]. Das sieht doch schon verdächtig nach unserem $this->data Array aus oder?
Erstellt man input-Felder mittels des Form-Helpers (welchen man immer verwenden sollte), so erstellt Cake automatisch ein dazugehöriges Label.
Stolperstein: Cake freut sich immer über $form->input, da nur dort automatisch Labels und Fehlernachrichten erstellt werden können. Daher benutzt wenn möglich immer $form->input(’feldname’,array(’type’)) anstatt beispielsweise $form->textarea.
Anschließend folgt noch ein Submit Button sowie das Form-End-Tag.
Hier eine kleine Übersicht über die verwendeten Befehle:
-
$form->create(‘Modelname’);
-
/*wird zu */
-
<form id=“PostAddForm” method=“post” action=“/eclipse/tutorial/posts/add/”>
-
$form->input(‘feldname’);
-
/*wird zu */
-
<div class=“input”><label for=“PostTitel”>Titel</label><input name=“data[Post][titel]” type=“text” maxlength=“50″ value=“” id=“PostTitel” /></div>
-
<div class=“input required”><label for=“PostInhalt”>Inhalt</label><textarea name=“data[Post][inhalt]” cols=“30″ rows=“6″ id=“PostInhalt”></textarea></div>
-
$form->submit(‘Buttonbeschriftung’);
-
/* wird zu */
-
<div class=“submit”><input type=“submit” value=“Speichern” /></div>
-
$form->end()
-
/* wird zu */
-
</form>
Die einzelnen Helperbefehle haben noch mehr Möglichkeiten, dazu aber später mehr, sonst wird es zu kompliziert.
Die Action selbst erreicht ihr unter der url www.example.com/posts/add
Schreibt nun einen schönen Titel und einen tollen Inhalt und versucht, die Daten abzuspeichern. Wenn alles korrekt verlaufen ist und ihr dem Tutorial bisher gefolgt seid, sollte euch eine rote Schrift entgegenleuchten “Der Beitrag wurde erfolgreich gespeichert”. Ihr befindet euch nun dank des Redirects wieder auf der Indexseite und könnt euren Beitrag an letzter Stelle der Tabelle nun begutachten. Cake hat automatisch das korrekte Erstellungsdatum hinzugefügt. Dies geschieht allerdings nur, wenn es sich in der Datenbank bei dem Tabellenfeld “created” um ein DATETIME Feld handelt.
Hatte ich nicht eben noch Datenvalidierung gesprochen? Richtig, genau um diese kümmern wir uns jetzt. Öffnet eurer Post-Model und tragt folgende Änderungen ein:
/app/models/post.php
Wir haben folgendes hinzugefügt:
Für den Titel des Beitrags wird verlangt, dass er etwas enthalten muss (VALID_NOT_EMPTY = Darf nicht leer sein) sowie dass er eine maximale Länge von 100 nicht überschreiten darf.
Beim Inhalt ist uns die Länge egal, hier möchten wir nur darauf achten, dass etwas eingegeben wurde.
Ruft nun nochmals die “Beitrag hinzufügen” Seite auf und versucht das Formular ohne Eingabe von Werten abzusenden. Es erscheint in schöner roter Schrift “Fehler”. Da dies dem Benutzer aber nicht den Grund erklärt, warum etwas falsch gelaufen ist, ändern wir den View nun ab:
/app/views/posts/add.ctp
-
<h1>Beitrag hinzufügen</h1>
-
‘required’=>‘Bitte dieses Feld ausfüllen’,
-
‘length’=>‘Das Feld darf nicht mehr als 100 Zeichen enthalten’
-
)
-
)
-
);?></p>
-
);?></p>
Beachtet, dass wir im Error-Array des Titelfeldes dieselben Keys haben wie im Model, dadurch weiß Cake, welche Fehlernachricht die richtige ist. Versucht ihn nun das Formular ohne Input abzusenden, so erscheint zweimal der Fehler “Bitte dieses Feld ausfüllen”. Toll oder? Mehr über die vielfältigen Möglichkeiten der Validierung erfahrt ihr zur Zeit am besten in der CakePHP Bakery.
Teil 2.7:
Posts löschen und editieren
Wir haben nun gelernt, Beiträge hinzuzufügen, nun möchten wir natürlich auch löschen und editieren können. Dazu ergänzen wir zuerst unsere Index Datei um ein paar Links:
/app/views/posts/index.ctp
-
<h1>Mein erstes Blog</h1>
-
<!– NEU –>
-
<!– Ende–>
-
<table>
-
<tr>
-
<th>Titel</th>
-
<th>Inhalt</th>
-
<th>Erstellt</th>
-
<!– Neu –>
-
<th>Editieren</th>
-
<th>Löschen</th>
-
<!– Ende–>
-
</tr>
-
<?php foreach($posts as $post):?>
-
<tr>
-
<!– NEU –>
-
<td><?php echo $html->link(‘Löschen’, ‘/posts/delete/’.$post[‘Post’][‘id’], null, ‘Wirklich löschen?’);?></td>
-
<!– Ende –>
-
</tr>
-
<?php endforeach;?>
-
</table>
Wie ihr seht, wurden drei Links hinzugefügt. Wir können nun einfacher neue Beiträge hinzufügen und haben noch zwei zusätzliche Optionen bei jedem Eintrag, löschen und editieren. Kümmern wir uns zuerst um den Löschen Link (Ihr habt sicherlich inzwischen einige komische Einträge in der Liste, die dort nicht hingehören).
Wie ihr sicherlich bemerkt habt, sieht der Löschen Link etwas anders aus, er hat zwei zusätzliche Werte, null und Ein String ‘Wirklich löschen?’. Der NULL Wert ist ein Platzhalter der Funktion, an diese Stelle kommt wenn ihr es braucht ein array mit HTML Attributen (wie array(’class’=>’link)). Der String ist eine sogenannte Confirmation Message. Klickt ihr auf den Löschen Link wird euch zunächst ein Javascript Fenster präsentiert, bei dem ihr bestätigen müsst, ob ihr das Element wirklich löschen wollt. Toll, nicht?
Allerdings ist das ganze noch etwas funktionslos, daher editieren wir unsere Controller Datei nun:
/app/controllers/posts_controller.php
-
<?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());
-
}
-
-
-
function add() {
-
if ($this->Post->save($this->data)) {
-
$this->Session->setFlash(‘Der Beitrag wurde erfolgreich gespeichert’);
-
$this->redirect(‘/posts’);
-
} else $this->Session->setFlash(‘Fehler’);
-
}
-
}
-
-
/*NEU*/
-
function delete($id = NULL) {
-
if ($this->Post->del($id)) {
-
$this->Session->setFlash(‘Der Beitrag wurde erfolgreich gelöscht’);
-
$this->redirect(‘/posts’);
-
} else {
-
$this->Session->setFlash(‘Fehler’);
-
$this->redirect(‘/posts’);
-
}
-
}
-
}
-
/*ENDE*/
-
}
-
-
?>
Lasst mich euch die neue Funktion kurz eklären. Wenn eine ID an die Funktion übergeben wurde, versucht Cake mittels $this->Model->del($id) den entsprechenden Datensatz aus der Datenbanktabelle mit dem Model Post zu löschen. Ist dies erfolgreich, findet man sich mit einer Bestätigungsnachricht auf der Startseite wieder. Sollte dies aus irgendwelchen Gründen fehlschlagen, wird man ebenfalls zur Startseite geleitet. Dies spart euch einen View, den man ansonsten für die Delete Funktion schreiben müsste.
Hier kommt auch das URL Aussehen von Cake zum Einsatz, denn jede Cake URL ist nach einem bestimmten Schema aufgebaut:
Domain.com/controller/action/argument1/argument2/argument3, wobei die Argumente als Werte an die entsprechende Action im Controller übergeben werden.
Die Editierfunktion
Zu guter Letzt fehlt noch die Editiermöglichkeit. Fügt zuerst die Controller Action hinzu:
/app/controllers/posts_controller.php
-
<?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());
-
}
-
-
-
function add() {
-
if ($this->Post->save($this->data)) {
-
$this->Session->setFlash(‘Der Beitrag wurde erfolgreich gespeichert’);
-
$this->redirect(‘/posts’);
-
} else $this->Session->setFlash(‘Fehler’);
-
}
-
}
-
-
-
function delete($id = NULL) {
-
if ($this->Post->del($id)) {
-
$this->Session->setFlash(‘Der Beitrag wurde erfolgreich gelöscht’);
-
$this->redirect(‘/posts’);
-
} else {
-
$this->Session->setFlash(‘Fehler’);
-
$this->redirect(‘/posts’);
-
}
-
}
-
}
-
-
/*NEU*/
-
function edit($id = NULL) {
-
if ($this->Post->save($this->data)) {
-
$this->Session->setFlash(‘Der Beitrag wurde erfolgreich geändert’);
-
$this->redirect(‘/posts’);
-
}
-
}
-
else {
-
$this->Post->id = $id;
-
$this->data = $this->Post->read();
-
$this->set(‘id’,$id);
-
}
-
}
-
/*ENDE*/
-
}
-
-
?>
Sind Formulardaten verfübar, versucht Cake diese zu speichern. Enthält das Formular eine ID, so führt Cake kein INSERT, sondern einen UPDATE Befehl des entsprechenden Datensatzes durch. Sind noch keine Formulardaten vorhanden, liest Cake den Datensatz aus und speichert ihn im Array $this->data. Dies ist wichtig, damit die Daten gleich in die Formularfelder geladen werden können. Mittels $this->set(’id’,$id) legen wir noch fest, dass die die Variable $id im View mit dem Wert aus $id im Controller belegt wird.
Der passende View sieht so aus:
/app/views/posts/edit.ctp
-
<h1>Beitrag editieren</h1>
-
‘required’=>‘Bitte dieses Feld ausfüllen’,
-
‘length’=>‘Das Feld darf nicht mehr als 100 Zeichen enthalten’
-
)
-
)
-
);?></p>
-
);?></p>
Huch, das sieht ja genauso aus wie unser add-View. Fast! Die einzige Änderung (bis auf den Titel) findet ihr in der zweiten Zeile. Da wir nun natürlich nicht die Add, sondern die Edit Action aufrufen möchten, wurde dem $form->create Befehl eine action=>edit spendiert. Ein Absenden des Formulars führt nun zu /posts/edit/id, denn unsere $id haben wir ja im Controller festgelegt.
Nun sollte es möglich sein, Daten zu editieren.
Damit endet das offizielle Blog Tutorial, doch meins geht noch einen Schritt weiter. Die Grundlagen von Cake sollten euch ein Begriff sein, ein einfaches Create, Read, Update, Delete (kurz CRUD) ist immer der Einstieg in ein neues Framework. Ich möchte euch allerdings noch ein bisschen mehr von Cake zeigen. Im nächsten Teil werdet ihr erfahren, wie man eine Kommentarfunktion einbaut und einen eigenen Helper erstellt.
Zum letzten Teil des Tutorials
Veröffentlicht am Dienstag, den 2. Oktober 2007 um 12:59 Uhr veröffentlicht
Du kannst einen Kommentar schreiben, oder einen Trackback auf deiner Seite einrichten.
32 Reaktionen zu “CakePHP 1.2 Blog Tutorial Teil 2”
-
CakePHP & DIEVOLUTION Blog » Blog Archiv » CakePHP 1.2 Blog Tutorial Teil 1
Am 2. Oktober 2007 um 13:04 Uhr[…] 02.10.2007: CakePHP 1.2 Blog Tutorial Teil 2 […]
-
Justin
Am 27. Oktober 2007 um 10:35 UhrKannst du machen diese Tutorial am Englisch? Mein Deutsch ist sehr schlecht, aber ich moechte der tutorial mit Cake 1.2 learnen. Kannst du hilfen mir? Mein eMail ist JustinLilly (a) gmail (punkt) com
-
Am 1. Dezember 2007 um 05:29 Uhr
Das Markup des Beispielcodes kann hier gesäubert werden: http://www.kolchose.org/simon/replaceMarkup/
-
Alexia
Am 7. Dezember 2007 um 12:26 UhrMoin moin
erstmal danke für deine Mühe.
ich hänge aber an einem punkt fest…
versuche ich das mit add , krieg ich folgende fehlermeldung raus…
Notice (8): Undefined variable: form [CORE\app\views\posts\add.ctp, line 3]
Context | Code
$this = array(”name” => “Posts”, “here” => “/kuchen/posts/add”, “parent” => null, “action” => “add”, “model” => null, “association” => null, “field” => null, “fieldSuffix” => null, “modelId” => null, “uses” => false, “helpers” => array, “viewPath” => “posts”, “layoutPath” => null, “viewVars” => array, “__scripts” => array, “pageTitle” => false, “models” => array, “base” => “/kuchen”, “layout” => “default”, “autoRender” => true, “autoLayout” => true, “params” => array, “hasRendered” => false, “loaded” => array, “ext” => “.ctp”, “subDir” => null, “themeWeb” => null, “plugin” => null, “pluginPath” => null, “pluginPaths” => array, “passedArgs” => array, “__passedVars” => array, “uuids” => array, “_log” => null, “webroot” => “/kuchen/”, “modelNames” => array, “data” => null, “webservices” => null, “cacheAction” => false)
$___viewFn = “G:\xampp\htdocs\kuchen\app\views\posts\add.ctp”
$___dataForView = array(”cakeDebug” => array)
$loadHelpers = true
$cached = false
$loadedHelpers = array(”Html” => array, “Session” => array)
$helper = array(”helpers” => null, “__active” => true, “valid” => false, “error” => false, “_userAgent” => “b3fdb3798093c037148757259c6f6f45″, “path” => false, “lastError” => null, “security” => null, “time” => 1197022621, “sessionTime” => false, “watchKeys” => array, “_log” => null, “base” => “/kuchen”, “webroot” => “/kuchen/”, “here” => “/kuchen/posts/add”, “params” => array, “action” => “add”, “data” => null, “themeWeb” => null, “plugin” => null)
$replace = “s”
$camelBackedHelper = “session”
$html = array(”tags” => array, “base” => “/kuchen”, “here” => “/kuchen/posts/add”, “params” => array, “action” => “add”, “data” => null, “_crumbs” => array, “__docTypes” => array, “helpers” => null, “webroot” => “/kuchen/”, “themeWeb” => null, “plugin” => null, “namedArgs” => null, “argSeparator” => null, “validationErrors” => null, “__tainted” => null, “__cleaned” => null, “_log” => null)
$session = array(”helpers” => null, “__active” => true, “valid” => false, “error” => false, “_userAgent” => “b3fdb3798093c037148757259c6f6f45″, “path” => false, “lastError” => null, “security” => null, “time” => 1197022621, “sessionTime” => false, “watchKeys” => array, “_log” => null, “base” => “/kuchen”, “webroot” => “/kuchen/”, “here” => “/kuchen/posts/add”, “params” => array, “action” => “add”, “data” => null, “themeWeb” => null, “plugin” => null)
$cakeDebug = array(”name” => “Posts”, “here” => “/kuchen/posts/add”, “webroot” => “/kuchen/”, “action” => “add”, “uses” => false, “helpers” => array, “params” => array, “data” => null, “paginate” => array, “viewPath” => “posts”, “layoutPath” => null, “viewVars” => array, “pageTitle” => false, “modelNames” => array, “base” => “/kuchen”, “layout” => “default”, “autoRender” => false, “autoLayout” => true, “components” => array, “view” => “View”, “ext” => “.ctp”, “__viewClass” => array, “output” => null, “plugin” => null, “cacheAction” => false, “persistModel” => false, “webservices” => null, “passedArgs” => array, “_log” => null, “modelClass” => “Post”, “modelKey” => “post”, “Session” => array, “Post” => array)
$BASE = “/kuchen”
$params = array(”pass” => array, “controller” => “posts”, “action” => “add”, “plugin” => null, “form” => array, “url” => array, “bare” => 0, “webservices” => null, “models” => array)
$page_title = falseBeitrag hinzufügen
Beitrag hinzufügen
create(”post”);?>
include - CORE\app\views\posts\add.ctp, line 3
View::_render() - CORE\cake\libs\view\view.php, line 765
View::render() - CORE\cake\libs\view\view.php, line 320
Controller::render() - CORE\cake\libs\controller\controller.php, line 664
Dispatcher::_invoke() - CORE\cake\dispatcher.php, line 280
Dispatcher::dispatch() - CORE\cake\dispatcher.php, line 248
[main] - CORE\app\webroot\index.php, line 84Fatal error: Call to a member function create() on a non-object in G:\xampp\htdocs\kuchen\app\views\posts\add.ctp on line 3
vielleicht kannst du mir ja weiterhelfen.
lieben Dank
Alexia -
Am 7. Dezember 2007 um 12:30 Uhr
Hi Alexia. Schau doch mal, ob du im PostsController auch den Formhelper eingebunden hast
var $helpers = array(‘Form’);
-
Alexia
Am 7. Dezember 2007 um 12:38 UhrDanke, du bist ein Schatz…
-
Alexia
Am 7. Dezember 2007 um 12:59 Uhrps:
das Hinzufügen von Blogeinträgen (add) funktioniert erst nach dem Hinnzufügen der Validierungsregeln.
Vorher gibt nur die Meldung “Fehler” aus -
Chris
Am 28. Dezember 2007 um 20:48 UhrBei mir wird die Standardseite ganz am anfang nicht ausgegeben. Ich habe mir die neueste Version runtergeladen “cake_1.2.0.5875-pre-beta”, die entpackten Dateien habe ich alle in den root des Server gepackt, beim aufrufen der Domain sollte normalerweise die Standardseite mit den Meldungen kommen, stattdessen wird nur eine weiße Seite angezeigt, woran kann das liegen?
-
Chris
Am 29. Dezember 2007 um 00:28 UhrAh ok, das Problem lag daran, dass ich die letzte “pre_build” verwendet habe. Nachdem ich mir die “latest nightly” installiert habe, läuft alles super

-
Chris
Am 29. Dezember 2007 um 14:49 UhrVielleicht noch ein kleiner Hinweis: Solltet ihr die Fehlermeldung “Cannot modify header information…” erhalten, dann liegt es daran, dass ihr entweder vor dem “” am Ende einer Datei.
-
David
Am 4. Januar 2008 um 22:02 UhrDanke für das tolle Tutorial! Allerdings hab ich am Anfang von Punkt 2.4 schon folgendes Problem:
“Not Found
The requested URL /testapp/posts was not found on this server.”
Mein Webserver findet anscheinend den Controller nicht?
-
Am 4. Januar 2008 um 23:28 Uhr
Schon gelöst: Es war ein mod_rewrite Problem. Beim Entpacken der cake distro sollte man aufpassen, dass man nicht nur den Inhalt des cake Ordners in seine webapp kopiert, sondern am Besten den ganzen Ordner und dann einfach umbenennt! Warum? Im Root des cake folders befindet sich ein .htaccess file, dass auf *NIX systemen klarerweise nicht sichtbar ist.
-
daniel
Am 9. Februar 2008 um 15:18 UhrSuper DAvid, da wäre ich wohl nie drauf gekommen.
HAtte eben dasselbe Problem….HAtte schon Angst so zu enden wie beim versuch mit dem Zend Framework.
Nun kann es weietrgehen mit Cake…. *freu* -
Am 12. Februar 2008 um 14:52 Uhr
hey, wirklich super tutorial.
aber in punkt 2.4 hat sich im code ein fehler eingeschlichen:
$this->set(‘posts’,$eintraege);
die Anführungszeichen um das posts führen bei mir zu einem fehler. ohne sie funktioniert’s.
vll hat ja noch jemand das problem gehabt

-
marcel
Am 13. Februar 2008 um 20:53 Uhrhi,
sehr schönes Tutorial…Aber wenn ich Einträge editiere und absichtlich ein Fehler produziere bekomme ich eine Fehlermeldung: “Undefined variable: id [APP\views\posts\edit.ctp, line 2]” warum?
-
Thomas
Am 22. Februar 2008 um 13:25 UhrHall. Finde das Tutorial auch sehr gut geschrieben und einfach verständlich. Allerdings habe ich eine allgemeine Frage zum Aufbau der Datenbanktabellen. Und zwar habe ich bei meinen eigenen Tabellen die IDs nicht “id” sondern “id[tabellenname]” genannt. Nun erhalte ich aber bei der view-Action einen Fehler, dass Cake die Spalte [tabele].id nicht finden kann. Muss demnach die ID immer “id” lauten oder kann man Cake mitteilen, dass die ID der Tabelle die Bezeichnung xyz besitzt? Ich müßte sonst mein ganzes Datenbankmodel umwerfen und das wird nicht gerade spaßig ;).
LG Thomas
-
Am 22. Februar 2008 um 13:38 Uhr
@Marcel: Es ist keine Fehlerabfangmethode enthalten. Das er undefined variable: id anzeigt, liegt einfach daran, dass es keine gültige ID gibt.
@Thomas: du kannst in jedem Model $primaryKey = “beliebiges_feld” setzen. Allerdings ist dies mehr ein Workaround als ein schönes Cake-Mittel. Generell sollte man immer versuchen, den Cake-Weg zu verfolgen, also den Konventation, anstatt die Konfiguration manuell zu übernehmen.
-
Am 22. Februar 2008 um 13:39 Uhr
@arne: Wie du das hinbekommst, ist mir allerdings schleierhaft
Wenn du die Anführungszeichen weglässt, müsste PHP doch annehmen, es handele sich bei posts um eine Konstante. Bei mir funktioniert es jedenfalls nur mit Anführungszeichen, ich habs auch bisher noch nirgends anders gesehen. -
Thomas
Am 22. Februar 2008 um 13:50 Uhr@dievo: also ist es besser (auch für zukünftige Projekte) die ID einer Tabelle immer als “id” zu bezeichnen und keinen abweichenden Namen zu verwenden. Habe ich das richitg verstanden?
-
Am 22. Februar 2008 um 13:52 Uhr
Exakt. Dann brauchst du dir überhaupt keine Gedanken mehr über die Verknüfungen zwischen den Tabellen zu machen, zumindest was IDs angeht. Ein einfaches $hasMany = array(’Tags’); reicht dann aus, um z.B. das Model post.php mit dem Model tags.php zu verknüpfen. Allerdings braucht es dann natürlich in der Tags-Tabelle noch ein Feld post_id. Aber das ist auch noch genauer im BlogTutorial beschrieben.
-
Mike
Am 21. März 2008 um 15:28 UhrVielen DAnk für das Tutorial. Ich probier mich gerade mit cakephp. Leider stehe ich vor einem Problem welches ich erst lösen muss bevor ich weiter über kann. Ich bin dem Tut soweit gefolgt. Mit dem Einrichten, Datenbank und Tabelle anlegen. Die Statusseite sagt dass alles soweit in Ordnung ist. Model und Controllers sind angelegt. Wenn ich jedoch die Seite aufrufe bekomme ich die Meldung dass die Datenbank Tabelle nicht gefunden wird.
Error: Database table cake_postss for model Posts was not found.
Notice (8): Use of undefined constant ‘Posts’ - assumed ‘‘Posts’’ [CORE\cake\dispatcher.php, line 508]
Dispatcher::__getController() - CORE\cake\dispatcher.php, line 508
Dispatcher::dispatch() - CORE\cake\dispatcher.php, line 134
[main] - APP\webroot\index.php, line 84
Ich habe schon versucht die Hochkommas zu ändern aber der Effekt bleibt der gleiche. Meine Version ist die 1.2.0.6311 beta.
Wäre Klasse wenn ich ein Tip bekäme der mir weiterhilft.
Gruss
Mike -
Am 21. März 2008 um 15:55 Uhr
Bei Cake werden Models in der Einzahl genannt. In dem Fall musst du das Model “Post” nennen, nicht “Posts”, da die zugehörige Datenbanktabelle immer in der Mehrzahl gebildet wird, verlangt er bei einem Model “Posts” natürlich nach einer Tabelle “postss”, was er nicht finden kann

-
Mike
Am 21. März 2008 um 18:27 UhrHi dievo,
vielen Dank für die schnelle Antwort.
Jedoch habe ich das Model wie im Tut auch post genannt, und nicht posts.Wenn ich in der controllers statt wie im tut angegeben:
var $name = ‘Post’;
eingebe, ändert sich die Error Ausgabe in
Error: Database table cake_posts for model Post was not found.
Jedoch bleibt der Fehler
Notice (8): Use of undefined constant ‘Post’ - assumed ‘‘Post’’ [CORE\cake\dispatcher.php, line 508]
Dispatcher::__getController() - CORE\cake\dispatcher.php, line 508
Dispatcher::dispatch() - CORE\cake\dispatcher.php, line 134
[main] - APP\webroot\index.php, line 84Also scheint es ein anderer Fehler zu sein.
gruss Mike
-
Mike
Am 22. März 2008 um 13:29 UhrHallo noch mal.
Ich habe nun so einiges ausprobiert, aber der Fehler
Use of undefined constant ‘Post’ - assumed ‘‘Post’’ [CORE\cake\libs\class_registry.php, line 128]
blieb immer egal wie ich es nannte.
Als letzten Versuch habe ich alle ‘Posts’ oder andere die in diesen Hochkommas eingebundenen Konstanten ersetzt durch ‘Posts’. Dananch waren fast alle Fehler weg bis auf einen in der Datei “index.ctp”.
Dort mußte ich die Zeile
link($post[’Post’][’titel’], “/posts/view/”.$post[’Post’][’id’]);?>
ersetzen durch
link($post[’Post’][’titel’], ‘“/posts/view/”’.$post[’Post’][’id’]);?>
Nun sind alle Fehler weg und ich kann mit dem Tut weitermachen.
Ich kann mir aber keine Reim darauf machen warum die Fehler bei anderen noch nicht aufgetreten sind.
Was ist bei mir anders ?
GrussMike
-
Mike
Am 22. März 2008 um 13:33 UhrNachdem ich nun mein letzten Post sehe scheint es ein Problem mit dem Zeichensatz im Browser zu sein. Ich vermute dass durch das Copy & Paste falsche Zeichen mit übernommen wurden obwohl dies anders dargestellt wurde.
Darauf muss man erst mal kommen.

-
Monzavi
Am 9. Mai 2008 um 09:36 UhrHallo liebe Leute,
Beim Speichern der Beiträge erhalte ich folgende Fehlermeldung:
Notice (8): Undefined variable: tihs [APP\controllers\posts_controller.php, line 17]
Code
function add() {
if(!empty($this->data)) {
if($tihs->Post->save($this->data)) {PostsController::add() - APP\controllers\posts_controller.php, line 17
Dispatcher::_invoke() - CORE\cake\dispatcher.php, line 268
Dispatcher::dispatch() - CORE\cake\dispatcher.php, line 240
require - APP\webroot\index.php, line 84
[main] - CORE\index.php, line 63
Notice (8): Trying to get property of non-object [APP\controllers\posts_controller.php, line 17]Code
function add() {
if(!empty($this->data)) {
if($tihs->Post->save($this->data)) {PostsController::add() - APP\controllers\posts_controller.php, line 17
Dispatcher::_invoke() - CORE\cake\dispatcher.php, line 268
Dispatcher::dispatch() - CORE\cake\dispatcher.php, line 240
require - APP\webroot\index.php, line 84
[main] - CORE\index.php, line 63Fatal error: Call to a member function save() on a non-object in C:\xampp\htdocs\cake_web\app\controllers\posts_controller.php on line 17
Kann mir jemand weiterhelfen? Namenskonventionen sind eingehalten, Groß-Kleinschreibung ist auch korrekt.
Bs: Windows XP Home
Umgebung: XAMPPvielen Dank,
H. Monzavi -
Monzavi
Am 9. Mai 2008 um 09:37 UhrPardon Leute!! Ich glaube ich brauche dringend eine Brille!!! Schon gelöst.
Danke.
H. Monzavi -
Am 9. Mai 2008 um 09:39 Uhr
hehe, kein Problem
Cake ist zum Glück sehr komfortabel wenn es um die Fehlersuche geht:
Notice (8): Undefined variable: tihs [APP\controllers\posts_controller.php, line 17] -
Break
Am 16. Mai 2008 um 18:38 Uhrhi, wenn ich die flash über $session->flash(); ausgebe dann hängt irgendwie immer ne ‘1′ hinterndran !?
woran kann das liegen
gruß break
-
darki
Am 25. Mai 2008 um 13:15 Uhrhi,
du (und auch das andere tutorial sowie die conventions) schreibst “Eine ID wird bei jeder Tabelle benötigt”
ich sitze gerade an einem großen projekt, wo ich bereits primary keys zum beispiel in form von rechnungsnummern vergeben habe.
braucht die tabelle nun noch einen zusätzlichen pk “ID”? oder kann ich meine verwenden, weil wenn jede tabelle