Symfony2: Einfaches Eventhandling

| 1 Kommentar

Beim letzten Mal habe ich ja schon über Eventregistrierung über Annotations mit Symfony2 geschrieben und will heute an das Thema Eventhandling anknüpfen.

Der Umgang mit dem Symfony2 Eventhandling ist wie schon erwähnt sehr einfach und flexibel und das macht wirklich Freude damit zu arbeiten.

Aktuell habe ich es mit verschiedenen Datenmodellen zu tun, die zwar irgendwie miteinander zu tun haben, jedoch über keine direkte Verbindung verfügen. Jedes dieser Datenmodelle kann geladen, gespeichert und auch wieder gelöscht werden.

Zu jeder Aktion gehört noch ein Zeitpunkt, d.h. der oder die Listener können vorher oder nachher benachrichtigt werden und beim Speichern wollen unsere Listener vielleicht sogar wissen, ob der Datensatz neu erstellt wurde oder ob es sich nur um ein Update handelt.

Diese Anforderungen sind ansich recht übersichtlich, aber doch komplex genug, um ein wenig darüber zu schreiben.

Alle Modelle werden durch ein Resource-Modell verarbeitet und an dieser Stelle werden auch die Events ausgelöst. Es gibt für jede Aktion eine eigene EventKlasse die von einer ModelEvent-Klasse erbt und diese wiederum von Symfony-Event.

                        +-------------+
                        |    Event    |
                        +-------------+
                               |
                      +-----------------+
                      |    ModelEvent   |
                      +-----------------+
                      | get/setModel()  |
                      +-----------------+
                               |
         +---------------------+----------------------+
         |                     |                      |
+-----------------+   +-----------------+   +-------------------+
| ModelFindEvent  |   | ModelSaveEvent  |   | ModelDeleteEvent  |
+-----------------+   +-----------------+   +-------------------+
                      | - bool:isNew    |
                      | bool:isCreate() |
                      | bool:isUpdate() |
                      +-----------------+

Mein einfaches ASCI-Art UML verrät ja nun auch schon ein wenig darüber, wie die Aufgaben im System verteilt werden. Da beim Speichern das meiste passiert, sehen wir uns einfach mal die Save-Methode des Resourcen-Modells an. Die verwendeten Methoden, z.B. triggerEvent() sind in den Elternklassen definiert und nutzen den globalen Event-Dispatcher.

<?php
// ...
public function save(Model\Model $model) {
    $event = new Event\ModelSaveEvent($model);

    $this->triggerEvent('model.save.before', $event);
    $this->executeSave($model);
    $this->triggerEvent('model.save.after', $event);

    return $this;
}
// ...

Zuerst wird ein ModelSaveEvent-Object mit der Modelinstanz erzeugt und das erste Event (model.save.before) ausgelöst. Die ModelSaveEvent-Klasse erkennt nun anhand einer Methode im Model, ob dieses neu ist oder ein weiteres Mal gespeichert werden soll und merkt sich diesen anfänglichen Zustand. Dadurch kann dann auch nach dem Speichern noch festgestellt werden was passiert ist.

Danach wird eine protected Methode executeSave() aufgerufen die sich um die eigentliche Arbeit kümmert und anschliessend wird das zweite Event (model.save.after) ausgelöst.

Was haben wir dadurch nun erreicht? Wie ich im letzten Artikel schon beschrieben habe, lassen sich ja ganz einfach mehrere Events von einem Listener überwachen.

In der jeweiligen Methode könnten wir dann allgemein auf alle ModelEvents reagieren oder auch nur auf spezielle. Da wir mit dem Event auch eine Modelinstanz übergeben, können wir auch hier anhand des Types weitere Unterscheidungen machen, falls wir das müssen.

Leider geht uns bei einer Methode für alles das auslösende Event (z.B. “model.save.before”) verloren und damit auch der Zeitpunkt, wann was passiert ist.

Hier fände ich es angenehm, wenn der Symfony-Event-Dispatcher diese Information mit den Events mitgeben würde, aber man kann ja nicht alles haben und zur Not baut man es eben selbst dran. :-)

 

Ein Kommentar

  1. Pingback: Symfony2: Einfaches Eventhandling, die Zweite… – ebene7

Hinterlasse eine Antwort

Pflichtfelder sind mit * markiert.


Schlagwörter: A/B-Test, AbstractType, Adapter, AddOn, Administration, Ajax, Amazon, Animation, Annotations, Anonyme Klasse, Ant, Apache, API, Array, ArrayAccess, Attachment, Auftrag, Ausbildung, Auswertung, Authentifizierung, AutoLoader, AWS, Bedienung, Bedingung, Benchmark, Berechtigung, Berlin, Bildbearbeitung, Bildschirmfoto, Blog, Blogroll, BOM, Bootstrap, Bot, Browser, Bugtracker, Byte Order Mark, Bücher, Cache, CakePHP, Call-Center, Callback, CamelCase, Canvas, Captcha, CDN, Cheatsheet, CLI, Clickout, Closure, Cloud, CodeSniffer, Collection, Community, Comparator, Config, Contest, Controller, Converter, CouchDB, Countable, Cronjob, CRUD, CSS, CSV, CustomLibrary, Custom_Model, Daemon, Data Mapper, Datei, Datenbank, Datenstruktur, Datentypen, Dating, Datum, Debug, Decorator, Dekorierer, Design, Design Patterns, Doctrine, Dokumentation, Dump, Duplikat, each, EC2, Eclipse, Email, Entwicklung, Entwurfsmuster, Enum, Erweiterung, Event, Eventhandling, Exception-Handling, Extension, Facebook, Factory, Fallback, Fehler, Fehlermeldung, Filter, Firefox, Flash, flexigrid, Foreach, Formatierung, Formular, Framework, FTP, Funktion, Futon, ga:pi(), Getter, Google Analytics, Hash, Hash-Bang, Header, htaccess, HTML5, htpasswd, HTTP, HTTPS, IDE, If, Implementierung, InnoDB, Interceptor, Interface, Internet Explorer, isset, Iterator, Java, JavaScript, Job, jQuery, Kommentar, Konfiguration, Konsole, Kontrollstruktur, kopieren, kostenlos, Kundenbetreuung, Late Static Binding, Layout, Links, Linux, Listeners, Lizenz, Logging, Löschen, Magento, Magic Methods, Manual, ManyToMany, Marketing, Methode, Model, Monolog, MVC, MySQL, NetBeans, Network, Nirvanix, Objekt, Observable, Observer, OneToMany, Online Tool, OOP, Open Source, Operator, OR-Mapper, Order, ORM, O’Reilly, Parameter, Partnersuche, Passwort, Performance, PHP, php.ini, PHP hates me, phpMyAdmin, PHPUnit, Plugin, Popup, Proxy, Prüfsumme, Prüfung, QR-Code, Qualitätssicherung, Query, Queue, Redesign, Refactoring, Reflection, Request, Response, Responsive Design, Rest-API, Rockstar, Rollback, Routing, S3, Samba, Scheifen, Schleife, Schutz, Screenshot, Secure Shell, Selbstreferenz, Server, Setter, setTimeout, Shop, Sicherheit, Sicherung, Sichtbarkeit, Singleton Pattern, Skin, SOAP, Social Network, Software, Sortierung, Sourcecode, Spam, Speicherproblem, Spickzettel, SPL, Splittest, SSH, SSL, Stammtisch, Statement, static, Statistik, Status, Stellvertreter, Strategy Pattern, Stream, String, Stuttgart, Stylesheet, Subversion, Sun VirtualBox, Support, SVN, Switch, Symfony, Symfony2, Symfony Live, Tag, Template, Template Method, Ternär Operator, Testing, Theme, Thumbnail, Tool, Tour, Tracking, Twig, Twitter, Type-Cast, Ubuntu, Umwandlung, Underscore, unset, Update, Upload, Url, User Story, Validierung, Vererbung, Versionskontrolle, Versionsnummer, Verzweigung, Video, Videospiel, Virtualisierung, Visitor Pattern, Vorschaubild, walk, Warteschlange, Webserver, Webservice, Weiterleitung, Werkzeug, Windows, WindowsAzure, WordPress, Wrapper, Writer, XML, Youtube, Zeitschleife, Zeitsteuerung, Zend Framework, Zend_Application, Zend_Cloud, Zend_CodeGenerator, Zend_Http_Client, Zend_Reflection, Zend_Service, ZPress, Zugangskontrolle, Zugriffsmethode