MVC zusammensetzen
Die Business Objects und das Data Access Object (DAO) Model sind erstellt. Jetzt zeigen wir dir, wie du im Controller (C) über das DAO-Model (M) die Business Objects laden und der View (V) übergeben kannst.
Die Übersicht
Damit wir im Controller immer auf das DAO zugreifen können, laden wir das BlogDao
auf den Controller. Füge folgende Zeilen gleich nach der Annotationsmethode von qs\controller\BlogController
ein:
private $blogDao; private function _init(BlogDao $blogDao) { $this->blogDao = $blogDao; }
Über eine Dependency Injection holst du das BlogDao
und legst es auf dem Controller ab.
In der index()
Methode wollen wir alle Blog Artikel zeigen.
public function index() { // Artikel holen $blogArticles = $this->blogDao->getOnlineBlogArticles(); // Artikel der View übergeben $this->forward('..\view\overview.html', array('blogArticles' => $blogArticles)); }
Dazu holen wir die $blogArticles
über $this->blogDao->getOnlineBlogArticles()
und übergeben sie der View als Parameter.
Passe nun qs\view\overview.html.php
wie folgt an:
<?php use n2n\impl\web\ui\view\html\HtmlView; use n2n\web\ui\view\View; use qs\bo\BlogArticle; $view = HtmlView::view($this); $html = HtmlView::html($view); // Blog Artikel aus den Parametern auslesen $blogArticles = $view->getParam('blogArticles'); $view->useTemplate('boilerplate.html', array('title' => 'Übersicht')); ?> <h1>Unsere Blogartikel</h1> <?php foreach ($blogArticles as $blogArticle): $view->assert($blogArticle instanceof BlogArticle) ?> <article> <h2><?php $html->out($blogArticle->getTitle()) ?></h2> <p><?php $html->out($blogArticle->getLead()) ?></p> <?php $html->linkToController($blogArticle->getUrlPart(), 'lesen') ?> </article> <?php endforeach ?>
In der View müssen wir als erstes über $view->getParam()
die Blog Artikel auslesen, welche wir im Controller an die View übergeben haben. Diese stehen nun als Array zur Verfügung und wir können mit foreach
darüber iterieren.
if
, foreach
oder andere Konstrukte verwenden. Wir arbeiten hier mit dem Doppelpunkt und endforeach
, endif
... Wir sind der Meinung, dass dies für unsere Views die übersichtlichere Variante ist.$view->assert()
benötigen wir, um in der IDE von der Autovervollständigung profitieren zu können und sicherzustellen, dass wir die richtigen Objekte erhalten haben.
echo
Funktion verwenden und die Ausgabe immer über den HtmlBuilder ($html
) machen?Mit $html->linkToController()
erhalten wir immer einen Link zum Pfad des aktiven Controllers. Über den ersten Parameter können wir den Pfad ergänzen. Da wir ihn mit der URL des Artikel ergänzen, erhalten wir den Pfad auf die Detail-Methode unseres Controllers. Das zweite Argument ist das Label für den Link. Mit dieser Anweisung verlinken wir also von der Übersicht auf die Detailansicht unseres Blogs.
Die Detailansicht
Passe jetzt im Controller die Methode detail() an:
public function detail(string $urlPart) { // Artikel holen $blogArticle = $this->blogDao->getBlogArticleByUrlPart($urlPart); // prüfen, ob artikel gefunden if ($blogArticle === null) { throw new PageNotFoundException('Invalid urlPart: ' . $urlPart); } // Artikel weiterleiten $this->forward('~\view\detail.html', array('blogArticle' => $blogArticle)); }
Da wir das $blogDao
auf dem Controller gespeichert haben, können wir über $this
auch in dieser Methode darauf zugreifen und über ->getBlogArticleByUrlPart()
direkt den $blogArticle
auslesen, zu dem $urlPart
passt.
Jetzt ist es wichtig, dass wir prüfen, ob wir einen $blogArticle
erhalten haben. Wenn nicht, kannst du eine PageNotFoundException
werfen. Damit generiert n2n eine 404 Fehlerseite. Übergebe eine logische $message
als Parameter, damit du immer weisst, wo die 404 Fehlermeldung verursacht wurde.
In der forward()
Methode siehst du, dass wir wiederum davon Gebrauch machen, der View einen Parameter mitzugeben - nämlich den $blogArticle
.
Die Detail-View braucht etwas mehr Anpassung:
<?php use n2n\impl\web\ui\view\html\HtmlView; use n2n\web\ui\view\View; use qs\bo\BlogArticle; use n2n\l10n\DateTimeFormat; use n2n\io\managed\img\impl\ThSt; $view = HtmlView::view($this); $html = HtmlView::html($view); // Artikel aus den Parametern einlesen und überprüfen $blogArticle = $view->getParam('blogArticle'); $view->assert($blogArticle instanceof BlogArticle); // Kommentare vom Artikel auslesen $blogComments = $blogArticle->getComments(); // Artikel Titel wird an das Template übergeben $view->useTemplate('boilerplate.html', array('title' => $blogArticle->getTitle())); ?> <h1><?php $html->out($blogArticle->getTitle()) ?></h1> <p> <strong><?php $html->out($blogArticle->getLead()) ?></strong> </p> <strong>Artikel-Kategorien</strong> <ul> <?php foreach ($blogArticle->getCategories() as $blogCategory): ?> <li><?php $html->out($blogCategory->getName()) ?></li> <?php endforeach ?> </ul> <?php $view->out($blogArticle->getContentHtml()) ?> <?php $html->linkToController(null, 'Zur Übersicht') ?>
Zuerst lesen wir den Parameter $blogArticle
über $view->getParam()
aus. Die Kommentare des Artikels können wir direkt über $blogArticle->getComments()
auslesen. Beachte auch, dass wir dem Template den Titel unseres Artikels übergeben.
Weiter unten lesen wir dann auch noch die Kategorien des Artikels ($blogArticle->getCategories()
) aus.
Etwas Neues siehst du bei $view->out($blogArticle->getContentHtml())
. Hier können wir nicht $html->out()
verwenden, weil es die HTML Tags escapen würde. Um keine Sicherheitslücken aufzureisen ist es hier extrem wichtig, dass sichergestellt ist, dass im ausgegebenen HTML keine bösartigen Tags sein können!
contentHtml
statt nur content
Auch hier haben wir wieder $html->linkToController()
eingesetzt um auf eine andere Action Methode zu verlinken. Mit dem null
verlinken wir auf die Index-Methode des aktiven Controllers.
qs3
kontrollieren. Hier ist der ganze Code korrekt zusammengetragen. Du kannst das Modul mit http://localhost/[pfad-zum-public-folder-des-projektes]/blog3
aufrufen.