Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Geleitwort des Fachgutachters
Vorwort
1 Einleitung
2 Einführung in eZ Components
3 Die Applikationsbasis
4 Fehlerbehandlung und Debugging
5 Konfiguration
6 Datenbankanbindung
7 ORM mit PersistentObject
8 Template
9 Übersetzung
10 Benutzereingaben validieren
11 Authentifizierung
12 Bildverarbeitung
13 Archive und Dateien
14 Mail
15 Logging
16 Diagramme
17 Feeds und Caching
18 Setup
A Inhalt der Buch-CD
Stichwort
Download: - ZIP, ca. 2,7 MB
Ihre Meinung?
<< zurück | Galileo Computing / <openbook> /eZ Components | vor >>
eZ Components von Tobias Schlitt, Kore Nordmann Das Entwickler-Handbuch
eZ Components geb., mit CD 454 S., 39,90 Euro Galileo Computing ISBN 978-3-8362-1073-7 |
| 7 ORM mit PersistentObject
|  | 7.1 Modell-Klassen
|  | 7.2 Konzepte
|  |  | 7.2.1 Active Record
|  |  | 7.2.2 Row Data Gateway
|  |  | 7.2.3 Persistent Object
|  | 7.3 Konfiguration
|  |  | 7.3.1 Basiskonfiguration
|  |  | 7.3.2 Relationen beschreiben
|  | 7.4 Benutzung
|  |  | 7.4.1 Eine Persistenz-Sitzung erzeugen
|  |  | 7.4.2 Objekte auffinden
|  |  | 7.4.3 Objekte manipulieren
|  | 7.5 Erweiterte Möglichkeiten
|  |  | 7.5.1 Über Abfragen manipulieren
|  |  | 7.5.2 Werte auffrischen
|  |  | 7.5.3 Direkt mit der Datenbank arbeiten
|  | 7.6 Fazit
## 7.4 Benutzung Nachdem Sie nun gelernt haben, wie Sie die Persistenz von PHP-Objekten konfigurieren, soll dieser Abschnitt die eigentliche Anwendung von PersistentObject erläutern. Zuerst muss dazu eine Instanz der Hauptklasse ezcPersistentSession erzeugt werden, die bei der Konstruktion über die Form und Lage der Konfigurationsdateien in Kenntnis gesetzt werden muss. Anschließend werden die in Kapitel 6, »Datenbankanbindung«, realisierten Datenbankabfragen auf die Verwendung von PersistentObject umgestellt. ### 7.4.1 Eine Persistenz-Sitzung erzeugen Alle Aktionen auf persistenten Objekten werden über eine Instanz der Klasse ezcPersistentSession abgewickelt. Bevor dies möglich ist, muss diese Instanz erzeugt und initialisiert werden, was im GP-Blog innerhalb der init()-Methode des Haupt-Controllers geschieht, nachdem die Datenbankverbindung hergestellt wurde.
    $session = new ezcPersistentSession(
        $db,
        new ezcPersistentCodeManager(
            dirname( __FILE__ ) . "/../persistent"
        )
    );
    ezcPersistentSessionInstance::set( $session );
Listing 7.9 Erzeugung einer Persistenz-Sitzung Um ihre Arbeit aufnehmen zu können, benötigt eine Persistenz-Sitzung zwei Informationen, die im Konstruktor übergeben werden:
1. | Eine Datenbankverbindung in Form einer ezcDbHandler-Instanz,
2. | einen Definitionsmanager, der den Zugriff auf die Konfigurationsdateien realisiert.
Die Datenbankverbindung in der Variablen $db wurde in Kapitel 6, »Datenbankanbindung«, vorgestellt und ist in der init()-Methode des Controllers bereits verfügbar. Der benötigte Definitionsmanager muss neu erzeugt werden. Er erhält als Parameter das Verzeichnis, in dem die Konfigurationsdateien zu finden sind. Das Verzeichnis wird an dieser Stelle relativ zur Position der aktuellen Datei, also zu classes/controller.php, referenziert. ezcPersistentCodeManager ist eine Implementation des Interfaces ezcPersistentDefinitionManager. Sie ahnen vermutlich bereits, dass Sie somit auch an dieser Stelle alternative Zugriffsarten verwenden oder gar alternative Konfigurationsformate einsetzen können. Beachten Sie jedoch, dass sich der Definitionsmanager nicht um das Laden der PHP-Klassen zu Ihren persistenten Objekten kümmert. Hierfür müssen Sie selbst sorgen, zum Beispiel mittels des eZ Components-Autoload-Mechanismus, der vom GP-Blog verwendet wird und bereits in Kapitel 2, »Einführung in eZ Components«, vorgestellt wurde. ezcPersistentCodeManager stellt eine rudimentäre Fassung eines Definitionsmanagers dar. Die erzeugte Instanz sorgt lediglich dafür, anhand des im vorhergehenden Abschnitt gesehen Namensschemas die benötigte Konfiguration für ein persistentes Objekt zu laden. Dies passiert on-the-fly, sobald Sie ein Objekt mittels ezcPersistenSession verarbeiten wollen. Letztendlich wird der optionale Singleton-Mechanismus der PersistentObject-Komponente verwendet, um die eingerichtete Sitzung überall in der Applikation verfügbar zu machen. Der hier verwendete Code-Manager ist so rudimentär, dass er den Ladevorgang bei jeder erneuten Anfrage der Definition wiederholt. Bei kleinen Applikationen wie dem GP-Blog stellt dies kein Problem dar. In realen Projekten ist es jedoch wünschenswert, dass eine einmal geladene Definition, die sich dann im Speicher befindet, wiederverwendet wird. Für diesen Zweck existiert die Klasse ezcPersistentCacheManager, die einen beliebigen Definitionsmanager einhüllt und zuerst überprüft, ob eine Definition bereits geladen wurde, und nur im Falle eines negativen Tests den internen Manager bemüht. Die alternative Konfiguration mittels ezcPersistentCacheManager sähe wie folgt aus:
    $session = new ezcPersistentSession(
        $db,
        new ezcPersistentCacheManager(
            new ezcPersistentCodeManager(
                dirname( __FILE__ ) . "/../persistent"
            )
        )
    );
    ezcPersistentSessionInstance::set( $session );
Listing 7.10 Konfigurationen cachen lassen eZ Components bringen von Hause aus noch einen weiteren Manager mit, über den es möglich ist, PersistentObject-Konfigurationen von mehreren verschiedenen Managern verarbeiten zu lassen. Dies kann nützlich sein, wenn Sie auf Definitionen aus verschiedenen Projekten zugreifen möchten oder falls Sie einfach ein wenig Struktur in die Konfigurationsdateien bringen wollen, falls Sie eine große Menge persistenter Objekte verwenden. Ebenfalls nützlich könnte es sein, wenn Sie für verschiedene Objekte unterschiedliche Konfigurationsformate verwenden, wobei eZ Components selbst zurzeit nur das gezeigte PHP-Format unterstützen. Der Konstruktor des ezcPersistentMultiManagers erwartet ein Array von ezcPersistentDefinitionManager-Implementierungen. Somit ist es sogar denkbar und sinnvoll, verschiedene Manager mit Hilfe eines Multi-Managers zu verbinden und diesen wiederum in einen Cache-Manager einzuhüllen. In einem solchen Szenario würde zuerst geprüft, ob eine Definition bereits geladen wurde. Ist dies nicht der Fall, würde der Multi-Manager im Anschluss versuchen, die Konfiguration von einem ihm übergebenen Manager zu laden. Diese Vorgehensweise ist flexibel und auch performant. Möchten Sie Ihren eigenen Definitionsmanager implementieren, so ist dies ein einfacher Schritt. Denkbar wäre es zum Beispiel, dass Sie Definitionen in einem XML-Format ablegen oder die Configuration-Komponente, zu der Sie schon näheres in Kapitel 5, »Konfiguration«, erfahren haben, verwenden, um Definitionen aus ini-Dateien zu lesen. Sie müssen lediglich die abstrakte Klasse ezcPersistentDefinitionManager erweitern, welche die Implementierung der folgenden Methode verlangt.
    public abstract function fetchDefinition( $class );
Listing 7.11 Signatur der Basisklasse für Definitionsmanager Sie sind also völlig frei in der Vorgehensweise, die Sie zum Laden der Definitionen verwenden und müssen lediglich dafür sorgen, die korrekte Definition zum übergebenen Klassennamen zu laden und ein entsprechendes Definitionsobjekt zurückzuliefern. Neben dieser abstrakten Methode implementiert die Basisklasse bereits die Methode setupReversePropertyDefinition(), mit deren Hilfe ein Reverse-Lookup zwischen den Spaltennamen der Datenbank und den Attributdefinitionen des geladenen Konfigurationsobjekts erzeugt wird.
    protected function setupReversePropertyDefinition(
        ezcPersistentObjectDefinition $def
    )
Listing 7.12 Signatur der setupReversePropertyDefinition()-Methode Wie Sie in Abschnitt 7.3.1, »Basiskonfiguration«, gesehen haben, werden die Property-Definitionen in ezcPersistentObjectDefinition anhand der Attributnamen identifiziert. Nach Aufruf von setupReversePropertyDefinition() ist auch eine Identifizierung anhand des Spaltennamens möglich. Sie müssen also diese Methode aus Ihrer Implementation von fetchDefinition() heraus aufrufen, um die korrekte Funktion von PersistentObject zu gewährleisten. ### 7.4.2 Objekte auffinden Nachdem die Instanz von ezcPersistentSession nun einsatzbereit ist, werden Sie sehen, wie Objekte damit aufgefunden werden können. Dazu stellt das Sitzungsobjekt verschiedene Möglichkeiten bereit. Zum einen können Objekte direkt geladen werden, was zum Beispiel in der Methode showEntry() der Aktionsklasse gpBlogActionEntryDisplay im GP-Blog Verwendung findet.
    $session = ezcPersistentSessionInstance::get();
    try
    {
        $entry = $session->load( "gpBlogEntry", (int) $id );
    }
    catch ( ezcPersistentiObjectException $e )
    {
        gpBlogController::getInstance()->mainSignals->emit(
            "error",
            "Entry with ID $id not found."
        );
        return;
    }
Listing 7.13 Ein einzelnes Modell-Objekt laden Vor dem hier dargestellten Ausschnitt der Aktion list_entries wurde bereits die ID des zu ladenden Eintrags mit Hilfe der Komponente Url ermittelt. Zunächst wird nun die im letzten Abschnitt erzeugte Instanz von ezcPersistentSession aus der Singleton-Implementierung geladen und in $session abgelegt. Im anschließenden try-Block wird die Persistenz-Sitzung angewiesen, das Objekt der Klasse gpBlogEntry mit der entsprechenden ID zu laden. Der hier verwendete Cast nach int resultiert daraus, dass die Url-Komponente keinen Schutz vor SQL-Injektion bietet. Schlägt das Laden des Objekts fehl, wirft die Session eine Exception, welche von ezcPersistentException ableitet. Im Normalfall wird dies eine ezcPersistentQueryException sein, falls kein Objekt gefunden wird. An dieser Stelle werden jedoch alle Exceptions des PersistentObject-Pakets gefangen und dem Benutzer mittels des Fehlersignals aus Kapitel 4, »Fehlerbehandlung und Debugging«, eine Fehlermeldung präsentiert. Sollten Sie erwarten, dass ein zu ladendes Objekt möglicherweise nicht existiert, können Sie alternativ die Methode loadIfExists() verwenden, die entweder das geladene Objekt zurückgibt oder null, falls kein Objekt mit der gegebenen ID existiert. Sollten Sie bereits eine Instanz des gewünschten Modells zur Hand haben, welches nur neu befüllt werden muss, können Sie auch auf die Methode loadIntoObject() zugreifen, die anstatt eines Klassennamens ein Objekt erwartet. Bevor Sie in Kürze die Suche nach Objekten kennenlernen, zeigen wir an dieser Stelle noch den Rest der Aktion. Bei der Darstellung eines einzelnen Eintrags werden zusätzlich die dazu passenden Tags und Kommentare ausgegeben. Aus Kapitel 3, »Die Applikationsbasis«, kennen Sie bereits das zur Anzeige verwendete display-Signal, welches hier nach wie vor verwendet wird. Die Funktionsweise des Signals an sich ist hier jedoch nicht von Bedeutung.
    gpBlogController::getInstance()->mainSignals->emit(
        "display",
        "schow_entry",
        array(
            "text" => sprintf(ð
        "Entry with ID %d:\n<h1>%s</h1>\n<p>%s</p><p><i>%s</i></p>",
                $id,
                $entry->title,
                $entry->body,
                date( "Y-m-d, H:i", $entry->date )
            ),
           "comments" =>ð
        $session->getRelatedObjects( $entry, "gpBlogComment" ),
            "tags"    =>ð
        $session->getRelatedObjects( $entry, "gpBlogTag" ),
        )
    );
Listing 7.14 Verbundene Objekte laden Die hervorgehobenen Zeilen zeigen, wie die zum geladenen Eintragsobjekt passenden Instanzen von gpBlogComment und gpBlogTag geladen werden. Die Methode getRelatedObjects() erwartet als ersten Parameter dasjenige Objekt, zu dem verbundene Objekte geladen werden sollen. Als zweiter Parameter wird die Klasse angegeben, von der die zu ladenden Objekte sind. Intern baut die PersistentObject-Komponente an dieser Stelle eine SELECT-Abfrage auf, die entsprechend der Konfiguration von persistenten Objekten und deren Relationen in der Datenbank sucht. Die Rückgabe der Methode ist immer ein Array von Objekten der übergebenen Klasse, auch wenn dieses Array eventuell leer ist. Als Alternative zu getRelatedObjects() existiert die Methode getRelated Object(), welche ein einzelnes Objekt liefert, allerdings auch eine Exception vom Typ ezcPersistentRelatedObjectNotFoundException wirft, falls das gewünschte Objekt nicht gefunden wird. Zusätzlich existiert die Methode createRelationFindQuery(), die analog zur Methode createFindQuery() arbeitet und im Folgenden vorgestellt wird. In der gleichen Aktions-Klasse, in der die soeben gezeigte Methode showEntry() zu finden ist, existiert die Aktion list_entries, welche alle verfügbaren Einträge anzeigt. Der Sourcecode der dazu passenden Methode listEntries(), die in Kapitel 3, »Die Applikationsbasis«, erstellt wurde, wird nun durch die folgenden Zeilen ersetzt:
    $session = ezcPersistentSessionInstance::get();
    $query = $session->createFindQuery( "gpBlogEntry" );
    $query->orderBy( "date" );
    gpBlogController::getInstance()->mainSignals->emit(
        "display",
        "list_entries",
        array(
            "entries" =>ð
        $session->findIterator( $query, "gpBlogEntry" )
        )
    );
Listing 7.15 Persistente Objekte auffinden Zunächst wird wieder die benötigte Persistenz-Sitzung in der Variablen $session gespeichert. Diesmal wird die Sitzung angewiesen, eine SELECT-Abfrage zu erzeugen, welche nach Instanzen der Klasse gpBlogEntry sucht. Neben der Tabelle, aus der selektiert wird, enthält dieses Query-Objekt alle zu selektierenden Spalten, die für das Objekt benötigt werden, sowie Aliase auf die entsprechenden Attributnamen. Durch Letztere ist es nicht nötig, dass Sie an dieser Stelle wissen, wie die Tabellenstruktur aufgebaut ist, sondern lediglich, welche Attribute die gpBlogEntry-Klasse definiert. In der darauf folgenden Zeile wird der Abfrage eine ORDER-BY-Klausel hinzugefügt, um die Einträge dem Datum nach sortiert zu erhalten. Zwar ist die SQL-Abstraktion dazu gedacht, plattformunabhängige SQL-Statements zu erzeugen, in diesem Fall lässt sich die Manipulation der Abfrage aber auch völlig unabhängig von SQL betrachten. Natürlich ist es hilfreich, dass Sie Kenntnisse von SQL mitbringen, notwendig ist dies allerdings nicht. Bei der Benutzung des Query-Objekts an dieser Stelle geht es lediglich darum zu spezifizieren, nach welchen Kriterien Objekte gefunden werden sollen. Die letzte hervorgehobene Zeile zeigt eine mögliche Variante, mit Hilfe des erzeugten Abfrageobjekts zu suchen. Die Methode findIterator() liefert eine Instanz der Klasse ezcPersistentFindIterator zurück, welche das PHP-Interface Iterator implementiert. [http://www.php.net/~helly/php/ext/spl/interfaceIterator.html ] Sie können das Objekt also mit einer foreach-Schleife verwenden oder manuell darüber iterieren. Der Vorteil dieser Implementierung gegenüber einem echten Array ist, dass nicht sofort alle Resultate von der Datenbank in den Speicher des PHP-Prozesses transferiert werden. Das Objekt empfängt in jeder Iteration nur das nächste Ergebnis. Gerade bei großen Ergebnismengen ist dieses Vorgehen sinnvoll. Alternativ zu findIterator() existiert die Methode find(), die ein normales Array der gewünschten Objekte liefert. Beiden Methoden muss neben dem Anfrage-Objekt erneut der Klassenname der zu suchenden Objekte übergeben werden, da anhand der Anfrage nicht genau bestimmt ist, welchen Objekttyp man als Ergebnis wünscht. Es könnte sein, dass eine Tabelle für verschiedene persistente Objekte verwendet wird und somit zu einem Tabellennamen mehrere Objektdefinitionen existieren. Die im letzten Beispiel angesprochene Methode createRelationFindQuery() erzeugt ebenfalls eine SELECT-Abfrage, welche mit den beiden hier vorgestellten Suchmethoden verwendet werden kann. ### 7.4.3 Objekte manipulieren Der letzte Schritt, der Ihnen nun noch im Umgang mit PersistentObject fehlt, ist die Manipulation von Objekten, also das Speichern, Aktualisieren und Löschen. Zunächst werden Sie sehen, wie neue Blog-Einträge gespeichert und bereits existierende aktualisiert werden. Beides passiert in der Methode save() der Aktions-Klasse gpBlogActionEntryEdit, die bereits in Kapitel 6, »Datenbankanbindung«, gezeigt wurde. Im Unterschied zum vorherigen Kapitel werden nun auch Tags berücksichtigt.
    if ( ( $id = $url->getParam( "id" ) ) !== null )
    {
        try
        {
            $entry = $session->load( "gpBlogEntry", (int) $id );
        }
        catch ( ezcPersistentObjectException $e )
        {
            gpBlogController::getInstance()->mainSignals->emit(
                "error",
                "Entry with ID $id not found."
            );
            return;
        }
    }
    else
    {
        $entry = new gpBlogEntry();
        $entry->date = time();
    }
    $entry->title = $_GET['title'];
    $entry->body = $_GET['body'];
    $session->saveOrUpdate( $entry );
    if ( isset( $_GET['tags'] ) && strlen( $_GET['tags'] ) > 0 )
    {
        self::addTags(
            $entry,
            array_map( "trim", explode( ",", $_GET['tags'] ) )
        );
    }
Listing 7.16 Speichern und Aktualisieren eines Eintrags Die benötigten Daten für den zu speichernden Eintrag werden provisorisch einfach aus dem $_GET-Array von PHP extrahiert, da Formulare im GP-Blog noch nicht zur Verfügung stehen. Sie folgen in Kapitel 10, »Benutzereingaben validieren«. Zunächst wird überprüft, ob aus der aufgerufenen URL die ID eines Eintrags extrahiert werden konnte. Ist dies der Fall, wird der gewünschte Eintrag – wie Sie es im vorherigen Abschnitt bereits kennengelernt haben – geladen. Falls die ID nicht gesetzt ist, wird eine neue Instanz von gpBlogEntry erzeugt und das aktuelle Datum eingesetzt. Nun steht in beiden Fällen ein Eintragsobjekt zur Verfügung, und sowohl der Titel als auch der Inhalt des Eintrags werden anhand der GET-Parameter gesetzt. Wir nehmen dabei keine Rücksicht darauf, ob diese Parameter gesetzt sind, sondern setzen dies stillschweigend an dieser Stelle voraus. Im Anschluss wird das Objekt mit Hilfe der Persistenz-Sitzung gespeichert. Um potentielle SQL-Angriffe brauchen Sie sich nicht zu sorgen, da PersistentObject intern Parameter-Bindung verwendet. Auf weitere Techniken zur Entwertung der vom Benutzer übergebenen Daten wird ebenfalls in Kapitel 10, »Benutzereingaben validieren«, eingegangen. Die Methode saveOrUpdate() entscheidet selbst, ob es sich um ein neues Eintragsobjekt handelt oder ob eine Aktualisierung vorgenommen werden muss. Wissen Sie explizit, dass es sich um ein neues Objekt handelt, können Sie alternativ die Methode save() verwenden. Analog dient die Methode update() zur reinen Aktualisierung eines Objekts. Beachten Sie jedoch, dass bei dem Versuch, ein bereits gespeichertes Objekt mittels save() zu speichern, eine ezcPersistentObjectAlreadyPersistentException erzeugt wird und analog dazu eine ezcPersistentObjectNotPersistentException, falls Sie versuchen, ein neues Objekt zu aktualisieren. Die Methode updateTags(), die ebenfalls in der Aktions-Klasse definiert wird, enthält den Code, um einem Eintrag Tags zuzuordnen. Wie Sie dem Code entnehmen können, wird eine kommaseparierte Liste von Tags mittels GET-Parameter übergeben. Dies ist zwar in gewissem Sinne unschön, aber für das Beispiel durchaus ausreichend. Der Aufruf von explode() erzeugt aus der Auflistung ein Array, in welchem die einzelnen Tags durch die Funktion trim() von überflüssigen Leerzeichen befreit werden. Im Folgenden finden Sie den Code von updateTags():
    private static function updateTags( gpBlogEntry $entry,ð
        array $tags )
    {
        $session      = ezcPersistentSessionInstance::get();
        $findTags     = $session->createFindQuery( "gpBlogTag" );
        $existingTags = $session->find( $findTags, "gpBlogTag" );
        foreach ( $existingTags as $id => $tag )
        {
            $existingTags[$tag->tag] = $tag;
            unset( $existingTags[$id] );
        }
        $assignedTags = $session->getRelatedObjects(
            $entry,
            "gpBlogTag"
        );
        foreach ( $assignedTags as $id => $tag )
        {
            $assignedTags[$tag->tag] = $tag;
            unset( $assignedTags[$id] );
        }
        foreach ( $tags as $tag )
        {
            if ( !isset( $existingTags[$tag] ) )
            {
                $existingTags[$tag] = new gpBlogTag();
                $existingTags[$tag]->tag = $tag;
                $session->save( $existingTags[$tag] );
            }
            if ( !isset( $assignedTags[$tag] ) )
            {
                $session->addRelatedObject(
                    $entry,
                    $existingTags[$tag]
                );
            }
            else
            {
                unset( $assignedTags[$tag] );
            }
        }
        foreach( $assignedTags as $tag )
        {
            $session->removeRelatedObject(
                $entry,
                $existingTags[$tag]
            );
        }
    }
Listing 7.17 Verbundene Objekte bearbeiten Zunächst wird die Persistenz-Sitzung bemüht, um eine Liste aller verfügbaren Tags zu erhalten. Da hier ein Array aller gpBlogTag-Objekte benötigt wird, kommt die Methode find(), statt wie im vorherigen Abschnitt findIterator(), zum Einsatz. Das zurückgegebene Array ist numerisch indiziert. Zum Vergleich, ob ein bestimmtes Tag bereits in der Datenbank existiert, wird jedoch der Name des Tags als Index benötigt. Aus diesem Grund wandelt die anschließende foreach-Schleife das Array entsprechend um. Im zweiten Schritt wird ein gleichartiges Array aller Tags erzeugt, die bereits mit dem Eintrag verbunden sind, wozu die getRelatedObjects()-Methode benutzt wird. Nun werden innerhalb einer dritten foreach-Schleife die vom Benutzer übergebenen Tags mit beiden erzeugten Arrays abgeglichen. Der erste if-Block testet, ob das aktuelle Tag überhaupt in der Datenbank existiert. Ist dies nicht der Fall, wird eine neue Instanz von gpBlogTag erzeugt, in der Datenbank abgelegt und in das $existingTags-Array aufgenommen. Im Anschluss wird überprüft, ob das aktuelle Tag dem Eintrag bereits zugeordnet ist. Im Fall eines neuen Tags ist dies natürlich nicht der Fall, allerdings kann es passieren, dass der Benutzer ein bereits existierendes Tag dem Eintrag neu zugeordnet hat. Ist das Tag noch nicht dem Eintrag zugeordnet, wird es entsprechend hinzugefügt. Im anderen Fall, wird das Tag aus dem $assignedTags-Array entfernt. Letztendlich werden die Relationen aller übrig gebliebenen Tags dieses Arrays vom Eintrag entfernt, denn diese wurden vom Benutzer nicht übermittelt. Die letzten beiden Aktionen, welche ebenfalls im Code hervorgehoben sind, interessieren an dieser Stelle am meisten, denn sie zeigen, wie Relationen aufgebaut und wieder aufgehoben werden können. Sowohl addRelatedObject() als auch removeRelatedObject() erwarten zuerst das Quellobjekt und dann das Zielobjekt. Sie erinnern sich, dass in Abschnitt 7.3.2, »Relationen beschreiben«, bereits auf die Einhaltung der Reihenfolge hingewiesen wurde: Einem Eintrag kann ein Tag zugeordnet werden, einem Tag aber kein Eintrag. Gleiches gilt für die Entfernung von verbundenen Objekten. Da die Rück-Relation als solche markiert wurde, wäre eine ezcPersistentRelationOperationNotSupportedException das Resultat.
Verbindungen speichern
Im hier vorliegenden Fall einer n:m-Beziehung ist es nicht notwendig, das Zielobjekt nach der Zuweisung erneut zu speichern, da n:m-Relationen mittels einer Verbindungstabelle realisiert werden. Die PersistentObject-Komponente erzeugt den entsprechenden Eintrag automatisch beim Aufruf von addRelatedObject() und löscht entsprechend beim Aufruf von removeRelatedObject(). Bei allen anderen Relationen funktioniert dieses Vorgehen nicht, da keine Relationstabelle existiert. Die Verbindung wird hier über den Eintrag des Zielobjekts direkt hergestellt und PersistentObject speichert dieses nicht automatisch, weder beim Etablieren noch beim Beseitigen einer Relation. Sie müssen sich also selbst um die Speicherung kümmern. Behalten Sie dies im Hinterkopf!
Nun fehlt aus dem Repertoire von PersistentObject noch die Möglichkeit, Objekte zu löschen. Um diese Möglichkeit zu illustrieren, wird eine neue Aktions-Klasse mit dem Namen gpBlogActionEntryDelete erzeugt, in der die Aktion delete_entry mittels einer entsprechenden Methode delete() realisiert wird. Wie Sie Aktions-Klassen schreiben, haben Sie bereits in Kapitel 3, »Die Applikationsbasis«, gesehen, weshalb wir an dieser Stelle nur auf die wesentlichen Elemente der delete()-Methode eingehen.
    if ( ( $id = $url->getParam( "id" ) ) !== null )
    {
        try
        {
            $entry = $session->load( "gpBlogEntry", (int) $id );
        }
        catch ( ezcPersistentObjectException $e )
        {
             // Fehler
        }
    }
    else
    {
        // Fehler
    }
    $session->delete( $entry );
Listing 7.18 Persistente Objekte löschen Das Vorgehen am Anfang dieser Methode kennen Sie bereits: Der Eintrag zur übergebenen ID wird geladen, und falls kein passender Eintrag existiert, wird ein Fehler signalisiert. Ganz am Ende der Methode wird der geladene Eintrag mit Hilfe von ezcPersistentSession->delete() aus der Datenbank gelöscht. Dieser sehr unscheinbare Aufruf zieht weitreichende Konsequenzen nach sich: Zum einen wird der Eintrag aus der Datenbank entfernt. Des Weiteren werden automatisch alle Kommentare entfernt, die diesem Eintrag zugeordnet sind. Wie Sie sich erinnern, wurde in Abschnitt 7.3.2, »Relationen beschreiben«, für diese Verbindung das $cascade-Flag auf true gesetzt, was dieses Verhalten hervorruft. Außerdem werden sämtliche Zeilen zu diesem Eintrag aus der Verbindungstabelle zwischen Einträgen und Tags gelöscht. Dieses Verhalten der Persistenz-Sitzung musste nicht explizit konfiguriert werden und wird automatisch von PersistentObject für alle n:m-Beziehungen implizit ausgeführt. ### Ihr Kommentar Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück | <top> | vor >>
Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen? Ihre Meinung
Buchempfehlungen
| PHP 5.3 und MySQL 5.1
| Besser PHP programmieren
| Webshops mit Magento
| Sichere Webanwendungen
| PHP 5.3 und MySQL 5.1 - Videotraining
| Apache 2
| Suchmaschinen- Optimierung für Webentwickler
| Joomla! 1.5
Shopping
Versandkostenfrei bestellen in Deutschland und Österreich Info

Copyright © Galileo Press 2008
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

[Galileo Computing]
Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de