Sto costruendo un piccolo framework PHP in mvc (sì, ancora un altro), principalmente per scopi di apprendimento, e sto cercando di farlo nel modo giusto, quindi mi piacerebbe usare un contenitore DI, ma non lo sono chiedendo quale usare ma piuttosto come usarne uno.
Senza entrare troppo nel dettaglio, il mvc è diviso in moduli che hanno controller che visualizzano le viste per le azioni. Ecco come viene elaborata una richiesta:
- un oggetto principale crea un'istanza dell'oggetto Request e un router e inietta la richiesta nel router per capire quale modulo è stato chiamato.
- quindi crea un'istanza dell'oggetto Module e invia la richiesta a tale
- il Modulo crea un ModuloRouter e invia la Richiesta per capire il controllore e l'azione
- crea quindi il controller e il ViewRenderer e inietta ViewRenderer nel controller (in modo che il controller possa inviare i dati alla vista)
- ViewRenderer deve sapere quale modulo, controller e azione sono stati chiamati per capire il percorso degli script di visualizzazione, quindi il Modulo deve capire questo e iniettarlo nel ViewRenderer
- il Modulo chiama quindi il metodo di azione sul controller e chiama il metodo di rendering su ViewRenderer
Per ora, non ho alcun contenitore DI configurato, ma quello che ho sono un mucchio di metodi initX () che creano il componente richiesto se non lo sono già. Ad esempio, il modulo ha il metodo initViewRenderer (). Questi metodi init vengono richiamati subito prima che quel componente sia necessario, non prima, e se il componente era già impostato non lo inizializzerà. Ciò consente di commutare i componenti, ma non è necessario impostarli manualmente se non ci sono.
Ora mi piacerebbe farlo implementando un contenitore DI, ma mantenendo comunque la configurazione manuale al minimo, quindi se la struttura della directory e la convenzione di denominazione sono seguite, tutto dovrebbe funzionare, senza nemmeno toccare la configurazione.
Se utilizzo il contenitore DI, lo inserisco quindi in ogni cosa (il contenitore si inietterà automaticamente durante la creazione di un componente), in modo che altri componenti possano utilizzarlo? Quando registro i componenti con il DI? Un componente può registrare altri componenti con la DI durante l'esecuzione? Creo una configurazione "comune" e la uso? Come faccio quindi a capire al volo quali componenti ho bisogno e come devono essere impostati?
Se Main usa il router che usa Request, Main deve quindi utilizzare il contenitore per ottenere il modulo (o il modulo deve essere trovato e impostato in anticipo? Come?) Il modulo utilizza il router, ma ha bisogno di capire le impostazioni per ViewRenderer e il controller al volo, non in anticipo, quindi il mio contenitore DI non può impostare quelli sul modulo prima che il modulo calcoli il controller e l'azione ...
Cosa succede se il controller necessita di qualche altro servizio? Inietto il contenitore in ogni controller? Se comincio a farlo, potrei semplicemente iniettarlo in tutto ...
Fondamentalmente sto cercando le migliori pratiche quando si tratta di cose come questa. So cosa è DI e cosa fanno i contenitori DI, ma sto cercando una guida per usarli nella vita reale, e non alcuni esempi isolati sulla rete.
Ci scusiamo per il lungo post e molte grazie in anticipo.
EDIT: dopo aver letto un po 'di più, sembra che iniettare il contenitore stesso in oggetti e farli usare il contenitore per trovare roba sia in realtà una posizione di servizio, non un'iniezione di dipendenza. Quindi la mia ultima idea è di usare le fabbriche per le cose che dovrebbero essere acquisite dinamicamente sulla base di qualcosa (come ottenere controllori basati su ciò che dice il router), e il contenitore verrebbe iniettato nelle fabbriche dove sarebbe usato più come un localizzatore di servizi . I componenti non dinamici verrebbero registrati in anticipo e quei componenti verrebbero creati dal contenitore e resi completamente operativi, con tutte le loro dipendenze riempite.
Quindi il flusso sarebbe simile a questo:
- ottiene Main dal container, Main viene iniettato con Request, Router e ModuleFactory che utilizza il container per trovare i moduli. Questo è tutto preconfigurato
- Main utilizza ModuleFactory per creare il modulo, iniettato con ModuleRouter, Request, ControllerFactory e ViewRenderer.
- Modulo utilizza ControllerFactory per creare un controller, iniettato con qualsiasi servizio da cui dipende, quindi il modulo chiama l'azione sul controller e invia il risultato al ViewRenderer per eseguire il rendering della vista.
Sto ottenendo ovunque con questo?