MVC zusammensetzen

Quickstart

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.

  1. Die Übersicht
  2. Die Detailansicht

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.

Beachte, dass wir in den Views keine geschweiften Klammern für 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.

Weisst du noch, weshalb wir in den Views keine 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!

Um uns der kritischen Eigenschaften von HTML Inhalten stetig bewusst zu sein, zeichnen wir Properties von BusinessObjects, welche HTML enthalten können, immer mit dem Zusatz html aus. Beispiel: 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.

Controller und Views

In diesem File haben wir BlogController, detail.html und overview.html für dich zum Download bereit.

Den Projektstand kannst du auch im Modul qs3 kontrollieren. Hier ist der ganze Code korrekt zusammengetragen. Du kannst das Modul mit http://localhost/[pfad-zum-public-folder-des-projektes]/blog3 aufrufen.
« Auf Daten zugreifen Formulare für Dateneingaben »

Kommentare

Du musst eingeloggt sein, damit du Beiträge erstellen kannst.

Fragen