Auf Daten zugreifen

Quickstart

Für den Zugriff auf Daten ist ein spezielles Model vorgesehen: das Data Access Object (DAO). Ein DAO ist für die Erstellung, Verwaltung und Löschung von Datensätzen verantwortlich. Eine kurze Einführung folgt hier.

  1. Das Data Access Object (DAO)
  2. Business Objects auslesen
  3. Business Objects speichern

Das Data Access Object (DAO)

Das Data Access Object ist ein Model. Erstelle die Klasse app/qs/model/BlogDao.php. Das Grundgerüst sieht wie folgt aus:

<?php
namespace qs\model;

use n2n\context\RequestScoped;
use n2n\persistence\orm\EntityManager;
use qs\bo\BlogArticle;
use n2n\io\managed\File;
use qs\bo\BlogComment;

class BlogDao implements RequestScoped {

    private $em;
    
    private function _init(EntityManager $em) {
        $this->em = $em;
    }
    
    // weitere Methoden folgen hier...
}

Beachte zuerst das RequestScoped Interface. Durch die Implementierung von RequestScoped wird erreicht, dass die Klasse pro Request nur einmal instanziert wird. Neben RequestScoped gibt es noch SessionScoped oder ApplicationScoped. Solche Models sind Lookupable. Dies bedeutet, dass sie über Dependency Injections in magischen Methoden geholt werden können. Lookupable führen bei der Instanzierung die _init Methode aus, welche private sein muss.

Die _init() Methode ist magisch. Das bedeutet, dass wir über eine Dependency Injection den EntityManager anfordern können. Mit dem EntityManager können wir auf Business Objects zugreifen. Weil wir ihn für alle unsere Zugriffe auf die Business Objects benötigen, speichern wir ihn auf dem Objekt.

Business Objects auslesen

Für die Übersicht unseres Modules benötigen wir eine Methode, welche uns sämtliche BlogArticle zurückliefert:

    /**
     * @return \qs\bo\BlogArticle[]
     */
    public function getOnlineBlogArticles() {
        $criteria = $this->em->createSimpleCriteria(BlogArticle::getClass(), array('online' => true), 
                array('id' => 'DESC'));
        return $criteria->toQuery()->fetchArray();
    }

Dazu erstellen wir auf dem EntityManager ($em) ein SimpleCriteria. Dieses kann mit folgenden Parametern umgehen:

Parameter Parameter Beispiel
\ReflectionClass Die Klasse der gesuchten Objekte BlogArticle::getClass()
array $matches Kriterien für die Auswahl. Muss als Array übergeben werden. array('online' => true) bewirkt, dass nur als Online gekennzeichnete Artikel ausgelesen werden
array $order Die Reihenfolge in welcher die Objekte zurückgeliefert werden. array('id' => 'DESC') bewirkt, dass die Objekte nach ID absteigend zurückgeliefert werden.
$limit Limit  
$num Anzahl Objekte wenn null, werden alle zurückgeliefert.

Um die Objekte zurückzubekommen, müssen wir das Criteria in ein Query umwandeln (toQuery()) und alle Objekte in einem Array zurückgeben (fetchArray()). Mit getOnlineBlogArticles() erhalten wir also ein Array mit allen Blog Artikeln, welche online gestellt sind. Der neuste zuerst.

In der Detailansicht benötigen wir einen einzelnen Artikel. Wir kennen aber nur die URL des Artikels, daher müssen wir den Artikel über die Eigenschaft  urlPart holen:

    /**
     * @param string $urlPart
     * @return \qs\bo\BlogArticle
     */
    public function getBlogArticleByUrlPart(string $urlPart){
        $criteria = $this->em->createSimpleCriteria(BlogArticle::getClass(), array('urlPart' => $urlPart));
        return $criteria->toQuery()->fetchSingle();
    }

Auch hier bilden wir ein Criteria und geben über $matches den $urlPart mit. Weil wir nur ein Objekt erwarten, geben wir über fetchSingle nur das gefundene Objekt zurück. So erhalten wir ein einzelnes Objekt zurück und nicht einen Array!

->fetchSingle() wirft eine Exception, wenn mehr als ein Resultat gefunden wird. Du darfst die Methode nur einsetzen, wenn du sicher bist, dass die Abfrage nur ein Resultat haben kann!
Wie könntest du sicherstellen, dass dir die Methode getBlogArticleByUrlPart() nur einen Artikel zurückgibt, welcher auch online ist?

Wir benötigen später auch noch eine Methode, um einen BlogArticle über seine ID zu holen. So geht's:

    /**
     * @param int $id
     * @return \qs\bo\BlogArticle
     */
    public function getBlogArticleById(int $id) {
        return $this->em->find(BlogArticle::getClass(), $id);
    }

Dies hätten wir natürlich auch über $em->createSimpleCriteria() machen können. Mit der find() Methode steht uns hier aber eine noch einfachere Möglichkeit zur Verfügung.

Der EntityManager stellt neben dem SimpleCriteria noch die Criteria API oder NQL als Möglichkeiten zur Verfügung, um Objekte auszulesen. Auf diese gehen wir aber im Rahmen des Quickstartes nicht näher ein.

Business Objects speichern

Zu guter letzt wollen wir noch die Möglichkeit haben, einen Kommentar zu speichern.

    public function saveComment(BlogArticle $blogArticle, string $email, string $content, File $image = null) {
        $comment = new BlogComment();
        $comment->setBlogArticle($blogArticle);
        $comment->setEmail($email);
        $comment->setContent($content);
        $comment->setImage($image);
        $this->em->persist($comment);
    }

Damit wir einen Kommentar speichern können, müssen wir wissen, für welchen Artikel wir diesen speichern. Darum erwarten wir einen BlogArticle. Weiter erwarten wir zwingend eine $email und etwas $content. Ob der Besucher auch ein Bild speichern will, wollen wir freiwillig lassen und erlauben beim $image darum null.

Der Inhalt der Methode besteht aus dem erstellen eines neuen Kommentars und der Übergabe der Eigenschaften über die Setter Methoden. Um den Kommentar zu speichern, müssen wir ihn persistieren ($this->em->persist($comment))

Das ist schon alles! Jetzt haben wir unsere Business Objects definiert und können auf sie zugreifen. Als nächstes bauen wir die Business Objects und unser DAO in unseren Controller und unsere Views ein!

BlogDao.php

Das vollständige Data Access Model zum downloaden

« Daten verwalten MVC zusammensetzen »

Kommentare

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

Fragen