zend framework

Dependency Injection in PHP (IoC Pattern)

Kurze Recherche zu Dependency Injection in PHP (Inversion of Control Pattern)

Erläuterungen zu DI und IoC http://martinfowler.com/articles/injection.html

Seit einiger Zeit ist das Thema DI in PHP recht aktuell mittlerweile gibt es einige selbständige Dependency Injection Container und einige DI Container welche aus einem Framework entstanden sind oder zu diesem gehören.

Folgende DI Lösungen in PHP habe ich auf die schnelle gefunden und kurz angesehen:

Wirklich getestet habe ich nur den Symfony DI Container, um das mal ein bisschen zu verdeutlichen hier eine Beispiel Konfiguration und ein bisschen Beispiel Code:

Als Konfigurationsformat habe ich XML ausgewählt die Konfiguration meines DI Containers für ein Beispiel Projekt sieht bei mir so aus

XML:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2.  
  3. <container xmlns="http://symfony-project.org/2.0/container">
  4.   <services>
  5.  
  6.     <!-- PageCache -->
  7.     <service id="pagecache" class="Zend_Cache" shared="true" constructor="factory">
  8.       <file>Zend/Cache.php</file>
  9.       <argument>Page</argument>
  10.       <argument>File</argument>
  11.       <argument type="collection">
  12.         <argument key="lifetime">3600</argument>
  13.         <argument key="default_options" type="collection">
  14.           <argument key="make_id_with_get_variables">true</argument>
  15.           <argument key="make_id_with_cookie_variables">false</argument>
  16.           <argument key="specific_lifetime">3600</argument>
  17.           <argument key="cache_with_session_variables">true</argument>
  18.           <argument key="cache_with_post_variables">true</argument>
  19.           <argument key="cache_with_get_variables">true</argument>
  20.           <argument key="tags" type="collection">
  21.             <argument>page</argument>
  22.           </argument>
  23.         </argument>
  24.         <argument key="lifedebug_header">false</argument>
  25.       </argument>
  26.       <argument type="collection">
  27.         <argument key="cache_dir">../tmp/</argument>
  28.       </argument>
  29.       <call method="start">
  30.       </call>
  31.     </service>
  32.   <!-- ENDE PageCache -->
  33.  
  34.  
  35.     <!-- Loggging -->
  36.     <service id="log" class="Logger" shared="true">
  37.       <argument type="service">
  38.         <service class="Zend_Log" shared="true">
  39.           <argument type="service">
  40.             <service class="Zend_Log_Writer_Stream" shared="true">
  41.               <argument>../log/debug.log</argument>
  42.               <call method="setFormatter">
  43.                 <argument type="service">
  44.                   <service class="Zend_Log_Formatter_Simple" shared="true">
  45.                     <argument>%%timestamp%%|%%sessionId%%|%%priorityName%%|%%fkn%%.%%line%%|%%message%%
  46.                     </argument>
  47.                   </service>
  48.                 </argument>
  49.               </call>
  50.             </service>
  51.           </argument>
  52.         </service>
  53.       </argument>
  54.       <call method="setLevel">
  55.         <argument>7</argument>
  56.       </call>
  57.     </service>
  58.     <!-- ENDE Loggging -->
  59.  
  60.   <!-- Cache -->
  61.     <service id="cache" class="Zend_Cache" shared="true" constructor="factory">
  62.       <file>Zend/Cache.php</file>
  63.       <argument>Core</argument>
  64.       <argument>File</argument>
  65.       <argument type="collection">
  66.         <argument key="automatic_serialization">true</argument>
  67.       </argument>
  68.       <argument type="collection">
  69.         <argument key="cache_dir">../tmp/</argument>
  70.       </argument>
  71.     </service>
  72.  
  73.   <!-- END Cache -->
  74.  
  75.   </services>
  76. </container>

Die Konfiguration bewirkt das ich in der Anwendung nachher einen PageCache, einen Logger und einen normalen Cache einsatzbereit zur Verfügung habe sobald ich diese benötig.

Ein Hinweis noch zu den möglichen Attributen der Service Node besonders praktisch sind hier die Attribute "shared" und "constructor" mit dem shared Attribut kann angegeben werden ob nur eine Instanz dieses Service erstellt wird und bei jedem Zugriff darauf die selbe Instanz zurück gegeben wird, oder ob immer eine neue Instanz zurück gegeben wird. Über die "constructor" Attribut kann angebeben werden ob es sich um einen statischen oder nicht statischen Aufruf handelt. Für Zend_Cache wird der Aufruf Zend_Cache::factory(Core, File,...) verwendet. An der Klasse Logger wird der Konstruktor mit den angegebenen Parametern aufgerufen.
Im PageCache Beispiel wird direkt nach der Erstellung des Objekts noch die Methode start() aufgerufen.

Innerhalb der Anwendung wird der Container folgendermaßen initialisiert und Verwendet:

PHP:
  1. require_once $basePath.'/lib/sf/sfServiceContainerAutoloader.php';
  2.  
  3. // Symfony Autoloader registrieren
  4. sfServiceContainerAutoloader::register();
  5.  
  6. // haben wir schon einen Fertigen DI Container?
  7. if (file_exists($configPath.'/di.container.conf.xml.php'))
  8. {
  9. require_once $configPath.'/di.container.conf.xml.php';
  10. $sc = new SampleServiceContainer();
  11. }
  12. else
  13. {
  14. // noch kein DI Container vorhanden, also aus XML erstellen
  15. $sc = new sfServiceContainerBuilder();
  16. $loader = new sfServiceContainerLoaderFileXml($sc);
  17. $loader->load($configPath.'/di.container.conf.xml');
  18. $dumper = new sfServiceContainerDumperPhp($sc);
  19. file_put_contents($file, $dumper->dump(array('class' => 'SampleServiceContainer')));
  20. }
  21.  
  22. // Folgende Aufrufe können dann innerhalb der Anwendung verwendet werden
  23. // Zugriff auf den Cache
  24. $cache = $sc->cache;
  25.  
  26. // Zugriff auf den Logger
  27. $log = $sc->log

noch Fragen? Doku anschauen ;-)

Zend_Log mit mongoDB

mal ein Kurzer Beitrag zu mongoDB.

Hab natürlich nur den PHP Treiber ausprobiert, Java wird aber wohl ähnlich wenn nicht gleich einfach zu bedienen sein.
Bin durch diesen Artikel draufgestoßen http://blog.mongodb.org/post/172254834/mongodb-is-fantastic-for-logging und hab es mal bei einem Projekt testweise eingebunden.

Zeigt zumindest mal einen Teil der Dinge in denen mongoDB gut ist:

- Asynchrone Inserts, daher kein warten auf ein File

- es gibt sogenannte Capped Collections, bei denen fliegen einfach die ältesten Daten aus der Collection raus (Konfigurierbar nach Anzahl der Objekte und Größe der Collection) quasi eine automatische rotation

- schnell

Um mongoDB zum Logging zu verwenden, hab ich lediglich einen neuen Zend_Log_Writer erstellt welcher die Logging Daten in eine mongoDB schreibt. Und diesen dem Logger zur Verwendung gegeben.

Dafür musste ich ungefähr 4 Zeilen Code selber schreiben:

...

$mongo = new Mongo();

$this->_db = $db->selectDB( "logs" )->createCollection(date('Y-m-d').'logs', true, 100000, 1000);

$this->_db->insert($dataToInsert);

...

der Rest der Arbeit bestand draus mir den Zend_Log_Writer_Db zu kopieren und die obigen Zeilen dort einzubauen.

Ok also was hat es gebracht? Gebracht hat es das ich jetzt die Anwendung mit fast vollem Log Level fahren kann und sich an der Geschwindigkeit zumindest spürbar nichts ändert.

Weitere Idee wäre zb, das man einen zentralen Logging Server hat und von anderen Anwendungen einfach dort hin schreiben kann.

mongoDB bietet auch so abgefahrene Sachen wie Replizierung und Fail-Over Lösungen.

Durchaus interessant wenn mal eine Datenbank gesucht wird in welche man einfach Objekte reinhauen kann.

Achso und den Server selbst aufsetzen war im Endeffekt nur mongoDb Archiv entpacken und mongod run aufrufen.

Links:

mongoDB

mongoDB Logger in Symfony

Ajax und Zendframework

Raphael erklärt ganz gut wie man zum Beispiel eine Ajax Action im Zendframework realisieren könnte...

-> zu Raphaels Blog

Zend Framework – Code Freeze und 0.9er Release

Das Zend Framework hat mittlerweile die Version 0.9 erreicht und es wurde ein Code Freeze vorgenommen. Dies bedeutet das ab jetzt bis zur 1.0er Version keine Änderungen mehr an der Api vorgenommen werden und keine neuen Features hinzugefügt werden. Es werden lediglich noch Fehler berreinigt.

Daher sollte auch jeder der sicht jetzt das Zend Framework runterlädt und anfängt zu Coden nachher ohne Probleme auf das Stable Release updaten können.

Für mich zum selber merken und falls jemand was ähnliches sucht mal ein paar Links rund um das Zend Framework.