Waar vul ik de Container?
Bij mijn MVC structuur heb ik een Kernel, waar je een Request object in stuurt en uiteindelijk een Response object uit krijgt om naar de client te zenden.
Na het hele routing proces, is er een Route gematcht, en returnt mijn Router een array met parameters. Deze ziet er zo uit:
Code (php)
1
2
3
4
2
3
4
array(
'route' => // Route object waarvan het pad matcht met de request URI.
'vars' => // de variabele gegevens uit de url. Het is een associatieve array zoals array('id' => 123). De keys zijn bepaald door het Route object
);
'route' => // Route object waarvan het pad matcht met de request URI.
'vars' => // de variabele gegevens uit de url. Het is een associatieve array zoals array('id' => 123). De keys zijn bepaald door het Route object
);
Vervolgens wordt in de kernel (waar ook de router wordt gebruikt om een route te matchen) de gereturnde array met parameters gebruikt.
Het Route object bevat alle informatie over de controller naam, en de action naam.
De controller wordt vervolgens geinstantieerd, en zo gaat alles verder.
Mijn Kernel is gewoon een class. Ik maak ook gebruik van een Container object.
Het Container object wordt geinstantieerd in de constructor van de Kernel class, en wordt vervolgens bewaard als een property in de Kernel.
Het Router object (dat in de kernel wordt gebruikt) wordt ook verkregen uit de Container.
Mijn vragen:
- Op welke manier 'vul' je de (Service)Container met de objecten, zoals de Router, de Mailer, Database, etc.
Wat voor mij belangrijk is, is dat het via pure PHP, maar ook via config bestanden moet kunnen. (de 'container configuratie')
- Op welke manier kan ik flexibel toegang krijgen tot de Container vanuit een controller?
Ik kan natuurlijk (in de kernel) bij het instantieren van de controller de Container meegeven via een controller constructor, maar daardoor moet elke controller verplicht een constructor hebben (en ook nog eens de juiste 'method signature' hebben, dus de juiste parameters accepteren).
- Wat is beter, alles zoals een Mailer object en een Database object in een controller, verkrijgen van een Container, of gewoon een nieuw Database/Mailer object instantieren?
Ik gebruikte in deze vraag even Database en Mailer objecten als voorbeeld van dingen die je wel eens nodig hebt in een controller.
Gewijzigd op 25/08/2016 21:14:02 door Jan terhuijzen
Leuke vragen :-)
Ik ben zelf fan van Symfony. Je zou daar zeker een kijkje moeten nemen.
Vraag 1:
Via Configuratie bestanden of pure PHP inderdaad. Als configuratie standaard zou ik vooral denken aan Yaml maar in mindere mate ook wel aan XML. Natuurlijk heb je aan enkel een configuratie bestand helemaal niets, je hebt immers ook een stukje PHP nodig die dat dan weer omzet in een array of een object. Daarnaast zul je een soort standaardisatie moeten maken die het mogelijk maakt op een eenduidige manier je objecten te omschrijven die je in de servicecontainer wilt hebben.
vraag 2:
Om makkelijk vanuit een controller bij de container te komen zul je container toch moeten injecteren in de controller class. Of je dat via de constructor doet of met een setter is jouw keuze. Ik zou voor een abstract controller class of baseController class liever geen constructor gebruiken omdat dit nu net een class is die veel ge-extend wordt door allerhande andere (controller-) classes en dan zit je met het aanroepen van parent::__construct(); hetgeen weer minder gebruiksvriendelijk is bij het allerdaags gebruik van de controllers.
vraag 3:
Een container is bedoeld om references van geïnstantieerde classes op te slaan. de geïnstantieerde classes zelf kunnen al veel voorbereidend werk gedaan hebben zoals het uitlezen van de benodigde configuratie instellingen bijvoorbeeld. een dergelijke instantie 'hergebruiken' is daarom sneller.
- Het "vullen" (eerder configureren) van de container is onderdeel van het instantiëren van je applicatie. Maak bijv. een ContainerLoader/ServiceProvider die de service configuratie definieert. Kijk als voorbeeld naar hoe Silex dat doet. Oh, en liever geen Yaml, maak je je leven alleen maar moeilijker mee ;)
- Je kan er ook voor kiezen je controller ook een service te laten zijn (niet echt voorstander van overigens). En anders gewoon inderdaad de container in de controller injecteren. In tegenstelling tot Frank zou ik deze wel in de constructor doen, een controller doet immers toch niks anders in de constructor. Tevens moet je telkens if (null !== $this->container) { ... } gebruiken als je een setter injection doet bijv., je weet immers nooit zeker of de container wel ingesteld is.
- Het hele feit van een container is het hergebruiken van dezelfde instance van een service. Ga dus nooit 20x een service opnieuw instantieren, dan heb je dependency injection compleet van de tafel geveegd.
Om eerlijk te zijn is mijn aanbeveling om te stoppen met het maken van je eigen framework en gewoon een framework (zie daar bijvoorbeeld Symfony, Laravel of Silex) te gebruiken. Met het maken van je eigen framework ga je je eigen design principes ontwikkelen, die wellicht niet goed zijn (zoals het elke keer aanmaken van nieuwe Mailer classes ipv de service gebruiken). Frameworks pushen je in de goede richting. Op deze manier gaat het maken van je eerste demo project (a) een stuk sneller en (b) meteen op een goede OO manier.
Gewijzigd op 27/08/2016 12:23:56 door Wouter J