2013-02-14 9 views
6

Ho appena iniziato a imparare Zend Framework 2 come sviluppatore di Zend Framework 1 da molto tempo. Sto avendo un piccolo problema a ricoprire la nuova terminologia.Zend Framework 2 - Applicazioni/Modules/Service Manager - Oh My

Indietro in ZF1, se volessi creare un logger che fosse globale per un'applicazione, aggiungerei la configurazione nel file application.ini e il bootstrap lo inizializzerebbe come risorsa (spero di averlo detto giusto) . Quindi, da qualsiasi controller del mio modulo, ho potuto accedere al registratore tramite le risorse bootstrap.

Immettere ZF2, i moduli sono un po 'diversi, sono autonomi, ma sono un po' confuso su come interagiscono con l'applicazione. Mi sembra che questo sia il punto in cui entra in gioco ServiceManager. Il mio obiettivo è quello di avere il mio modulo (non il controller, ma il modulo stesso), per verificare se l'applicazione ha definito un logger e, in caso affermativo, utilizzare quel logger in tutto il modulo. Se l'applicazione non definisce un logger, voglio che il modulo definisca il logger per la registrazione del modulo.

Questa domanda riguarda anche i database, diciamo che voglio che l'applicazione definisca la logica della connessione al database, mentre voglio che il modulo definisca la logica delle tabelle richieste. Come esattamente lo configuro e come/dove posso dire se c'è già una risorsa del database definita nell'applicazione.

Nota: ho eseguito la Quickstart di Rob Allen (informazioni sufficienti e l'unica risorsa che ho trovato che non ha ancora l'oscurità), e la ZF2 (readthedocs), e ho già cercato su google. Quello che sto scoprendo è che l'informazione è generalmente molto oscura quando si tratta di "dove" vanno alcuni pezzi del puzzle.

risposta

6

Ciò che si conosce da Zend Framework 1.x è una "risorsa di applicazione".

Il concetto di "risorsa applicazione" è sostituito in Zend Framework 2 dalla cosiddetta "services" (intro here)

Un altro cambiamento è moduli stessi. In ZF1, un modulo era principalmente una sottosezione della tua applicazione che gestiva alcune richieste. Questo non è più vero in ZF2: se il tuo modulo definisce un servizio o un controller, quello è ora accessibile a tutte le applicazioni. C'è una bella introduzione su alcuni differences between ZF1 and ZF2 by Gary Hockin.

Tuttavia, i moduli sono NON autonomo. Devono essere sviluppati in un ambiente isolato e con il minor numero possibile di dipendenze, ma forniscono funzionalità di interesse incrociato che riguardano tutte le applicazioni.

Per il tuo caso specifico del logger, suggerisco che il tuo modulo definisca sempre un logger e lo consumi. Cosa si può fare per definire il logger condizionale è la seguente:

class MyModule 
{ 
    public function onBootstrap($e) 
    { 
     // $e->getTarget() is the \Zend\Mvc\Application 
     $sm = $e->getTarget()->getServiceManager(); 

     if (!$sm->has('some-logger-name')) { 
      $sm->setFactory('some-logger-name', function ($sl) { 
       return new MyLogger($sl->get('some-db')); 
      }); 
     } 
    } 
} 

Si sarebbe quindi in grado di utilizzare il 'some-logger-name' in tutti la vostra applicazione.

Un approccio diverso è quello di definire solo i servizi logger e lasciare altri moduli o configurazioni ignorarlo seguito:

class MyModule 
{ 
    public function getConfig() 
    { 
     return array(
      'service_manager' => array(
       'factories' => array(
        'some-logger-name' => 'My\Logger\Factory\ClassName' 
       ), 
      ), 
     ); 
    } 
} 

stessa si ottiene con getServiceConfig, che è meno flessibile e non può essere memorizzato nella cache, ma ha una maggiore la priorità su getConfig (consente le sostituzioni) e consente di definire anche le fabbriche di servizio come le chiusure:

class MyModule 
{ 
    public function getServiceConfig() 
    { 
     return array(
      'factories' => array(
       'some-logger-name' => function ($sl) { 
        return new MyLogger($sl->get('some-db')); 
       }, 
      ), 
     ); 
    } 
} 

È quindi possibile anche definire una chiave di configurazione che deve essere utilizzato per decidere quale logger (servizio na me) da usare.

Il concetto con moduli e configurazioni è "l'ultimo modulo vince", quindi è possibile definire il servizio 'some-logger-name' nel modulo o in qualsiasi modulo caricato prima.

Gli stessi concetti si applicano anche alla connessione DB.

Come puoi vedere, passare ai servizi ti ha già dato un certo grado di libertà.

Ricorda che non è che "Applicazione" definisce qualcosa per te: i moduli definiscono i tuoi servizi/configurazioni/eventi ecc ... L'applicazione in esecuzione è quindi una composizione di tutte queste cose insieme.

+0

Apprezzo molto il resoconto scritto (e rapidamente guardato attraverso il link che hai fornito, approfondirò un po 'più tardi oggi). A causa della lotta che stavo svolgendo (parzialmente notato nel post di domanda sopra), ho anche iniziato a leggere il codice sorgente ZF2 per ottenere una migliore comprensione del flusso di lavoro. La tua risposta è spiegata molto bene insieme alla lettura del codice sorgente, sto iniziando a capire meglio come si integrano i pezzi. Non vedo l'ora di leggere (link) che hai fornito a prima vista sembra esattamente quello di cui ho bisogno per passare da ZF1 a ZF2! –

+0

Dato quanto nuovo è il rilascio di ZF2, insieme alla quantità di modifiche in corso a uno stile gestito dal servizio/evento, c'è un'enorme quantità di oscurità nelle informazioni disponibili finora (almeno da quello che ho trovato), I apprezzo molto il link che hai fornito in quanto sembra descrivere bene la transizione. –

+0

@AaronMurray master 'ServiceManager' e' EventManager' e tutto sembrerà molto più semplice. – Ocramius

3

Penso che, in particolare nel caso del logging, c'è un modo forse ancora migliore, sicuramente più incapsulato rispetto all'utilizzo dello ServiceManager. ZF2 è essenzialmente un framework basato su eventi e la funzionalità che consente a questa architettura basata su eventi può essere sfruttata a nostro vantaggio. La registrazione è un esempio perfetto per questo. Invece di definire una fabbrica, devi solo allegare un evento logger che può essere attivato da qualsiasi punto della tua applicazione.

Fissare un ascoltatore log evento nella vostra Module.php:

public function onBootstrap(MvcEvent $e) 
{ 
    //setup some $logger 

    $sharedManager = $e->getApplication()->getEventManager()->getSharedManager(); 

    $sharedManager->attach('*', 'log', function($e) use ($logger) { 
     /** @var $e MvcEvent */ 
     $target = get_class($e->getTarget()); 
     $message = $e->getParam('message', 'No message provided'); 
     $priority = $e->getParam('priority', Logger::INFO); 
     $message = sprintf('%s: %s', $target, $message); 
     $logger->log($priority, $message); 
    }); 
} 

Poi scattare da ovunque nell'applicazione, ad esempio, un controller:

$this->getEventManager()->trigger('log', $this, array(
    'priority' => \Zend\Log\Logger::INFO, 
    'message' => 'just some info to be logged' 
)); 
+0

non si tratta di avere un "logger" disponibile in tutto il modulo, ma fondamentalmente una spiegazione su come si usa l'event manager per risolvere i problemi trasversali. È bello, ma il commento in linea è in realtà la parte ricercata: P – Ocramius

+0

Ho in qualche modo capito cosa sta dicendo Markus (tramite il codice), e sono d'accordo con @Ocramius in quanto non è tanto il codice che stavo chiedendo riguardo ad esso era più capire come andare dalle "risorse" di Zend_Frameworks a dove ora definire le mie "risorse" in modo che siano accessibili a livello di applicazione. Sto iniziando a dipingere un'immagine più chiara con le informazioni in entrambe le risposte. Sospetto che ora trascorrerò la maggior parte del weekend a cogliere una buona padronanza su ModuleManager, EventManager e ServiceManager e penso che sarò "Convertito" –

+0

Devo notare che la cosa più difficile da superare è la logica degli eventi in un ambiente senza stato, ma viene da me :) –