In CakePHP stand ich bisher oft vor einem Problem wenn ich auf allen Seiten meiner Anwendung Daten aus einem bestimmten Controller brauchte.
Ein Anwendungsbeispiel: Ihr erstellt eine Eventdatenbank und wollt das in eurem Template z.B. in der Sidebar immer die nächsten 4 Events aus eurer Datenbank ausgegeben werden.
Das ist in sofern nicht ganz soooo easy, da CakePHP eigentlich immer nur das aktuelle Model ansprechen kann Wenn man sich also auf der Seite gerade die Userliste ( /users/ ) anschaut, und auf dieser Seite dann einen Aufruf zum Event-Model starten möchte würde es im Normalfall nicht so einfach funktionieren, da eben gerade nur das User-Model aktiv wäre.
Nun gibt es für dieses “Problem” viiiiele verschiedene Lösungen…
Einige Ansätze…
Eine Möglichkeit wäre z.B. im Template ein einfaches renderElement auszuführen, also sozusagen ein “Include”, dazu müsste man dann in dem jeweiligen Element noch einen Custom-SQLQuery schreiben und die Ergebnisse dann ganz normal mit PHP anordnen und ausgeben. Das mag ganz gut funktionieren, aber es führt zu Problem wenn Ihr z.B. euren Tabellennamen später ändern wollt oder Ihr Abhängigkeiten zwischen den Tabellen erzeugt habt, diese werden dann nämlich nicht mehr berücksichtigt. Also eine relativ unsaubere Lösung.
Eine weitere Möglichkeit wäre z.B. das Model für die gesamte Anwendung zu “aktivieren”, dafür könnte man in seiner app_controller.php ein $uses = array('Event'); anlegen. Unter Cake-Entwicklern ist jedoch auch dies eine nicht wirklich saubere Lösung. Es wird einfach zu viel Ballast mit geladen und es entspricht auch nicht dem eigentlichen Sinn der hinter dem MVC-Pattern steht.
Die dritte und aus meiner Sicht derzeit einfachste und beste Lösung funktioniert über sogenannte requestActions. Dafür legt man in seinem Controller (in unserem Fall events_controller.php) eine neue Action an die z.B. so aussehen könnte.
Die Action im Controller
function getEvents($limit = 4) {
if(isset($this->params['requested'])) {
$fetch = $this->Event->findAll('date > NOW()',null,null,$limit);
return $fetch;
}
}
Die erste If-Abfrage überprüft ob die Abfrage über eine requestAction erfolgt ist. Danach legen wir in $fetch alle Datensätze ab bei denen das Feld date größer ist als der aktuelle Zeitpunkt (NOW()). Zum Schluss der Abfrage limitieren wir noch die Anzahl der Datensätze auf $limit (Standardwert liegt hier bei 4 Datensätzen).
Der Aufruf im Template
Das wäre schon alles für den Controller. Kommen wir nun zu unserem Template, in unserem Fall die Datei default.thtml.
Dort fügen wir an der entsprechenden Stelle folgendes ein:
<?php echo $this->renderElement('eventlist'); ?>
Wer möchte kann dem Element natürlich noch Variablen mit auf den Weg geben die wir später dann zur Anforderung der Daten benötigen könnten.
Das Element
Nun bewirkt der obere Code das CakePHP die Datei app/views/elements/eventlist.thtml an dieser Stelle einbindet, daher legen wir diese Datei erst einmal an und könnten Sie danach mit folgendem Code betanken:
<?php
$events = $this->requestAction('/events/getEvents');
if(!empty($events)) {
echo '<ul class="s">';
foreach($events as $event):
echo '<li><a href="'.$html->url('/events/details/'.$event['Event']['id'].'').'">'.$event['Event']['name'].'</a></li>';
endforeach;
echo '</ul>';
}
?>
Also, was wird hier gemacht? Nun, über $events = $this->requestAction('/events/getEvents'); rufen wir die vorhin angelegte Action getEvents im Event-Controller ab, unabhängig davon, welcher Controller derzeit aktiv ist. Die durch die Action übergebenen Datensätze werden nun als Array in die Variable $events gepumpt. Danach schauen wir einfach noch ob auch wirklich Ergebnisse vorhanden sind und geben im Erfolgsfall alle Ergebnisse als unsortierte Liste aus.
Wer sehen möchte was sich im Array überhaupt befindet, der kann natürlich auch ein pr($events); ausführen.
Ihr könnt zudem auch das Limit der Datensätze beeinflussen, $events = $this->requestAction('/events/getEvents/50'); würde z.B. statt der 4 festgelegten Datensätze auf einmal 50 Datensätze abrufen.
Sehr einfach wie ich finde, zudem lässt sich eine Action somit sehr oft wiederverwenden.
Wie sich das ganze auf die Performance der Anwendung ausübt kann ich leider nicht sagen, ich habe bisher jedoch noch keinen Unterschied feststellen können. Es kommt aber sicherlich auch darauf an, wie oft man das ganze nutzt. Man sollte es daher mit den requestActions nicht übertreiben.
Kommentare zum Thema requestActions in CakePHP - Eine Anleitung:
Hallo,
wie Du bei einem Blick in die Google Groups zu Cake sehen wirst ist die request Action ein performance-Problem. Einige User berichten, dass schon bei zwei request-Actions pro Seite die Ladezeiten exponentiell ansteigen. Ich hatte einmal auf einer Seite 4 requestActions eingebaut, danach lud sie gar nicht mehr. Also bitte nur in Maßen verwenden :-)
Torsten
Kommentar-Feed für diesen Artikel
Kommentarfunktion für diesen Artikel geschlossen.
Ein neuer Blog verlässt die Produktionshalle Mal was zum Thema Musik in Magdeburg


Danke für den sehr schönen Artikel. Hab wieder was dazugelernt. Und CakePHP ist wirklich klasse.
Gruß,
J