container class
1) Stel je maakt een User object aan. Kun je deze dan ook gewoon in de container stoppen, zodat je het User object op andere plekken ook kunt gebruiken via $user = $this->getContainer()->get('user');
Mag dat gewoon?
2) Iemand (Wouter) zei onlangs dat je het gebruik van singletons moet zien te vermijden. Nu vraag ik me wel af... stel dat je in een of andere class zit en je wil van daaruit iets in de container stoppen, hoe haal je die Container dan op? Of laat je bijvoorbeeld iedere controller een "General Controller" extenden waarin een functie getContainer() aanwezig is?
Alvast vriendelijk dank voor de reacties.
Quote:
Mag dat gewoon?
Ja, dat is dependency injection!
Quote:
stel dat je in een of andere class zit en je wil van daaruit iets in de container stoppen, hoe haal je die Container dan op?
Over het algemeen is het zo dat je services/parameters op 1 plek, in bijv. een configuratie file (die abracadraba van gisteravond) oid, registreert en niet in een klasse. Behalve als je een ServiceProvider klasse gebruikt voor 1 specifiek onderwerp.
Quote:
Of laat je bijvoorbeeld iedere controller een "General Controller" extenden waarin een functie getContainer() aanwezig is?
Ja, dit doe je ook. Maar niet om dingen in de container te stoppen, meer om dingen uit de container te halen in controllers.
Je kan ook van je controller een service maken, dan moet je dit niet doen en dan moet je alleen de services die je gebruikt erin stoppen. Merk wel op dat ik nooit zal aanraden service van je controllers te maken, maar sommige mensen vinden het mooi...
https://github.com/rvandenberge/Framework/blob/master/vendor/framework/lib/Framework/DependencyInjection/ServiceLoader.php
En het config bestand waar alle services staan: https://github.com/rvandenberge/Framework/blob/master/config/services.php
Raoul, dat is nog niet echt dependency injection. Je inject helemaal nergens services.
Wouter J op 02/02/2013 19:12:52:
Raoul, dat is nog niet echt dependency injection. Je inject helemaal nergens services.
Op lijn 22 (https://github.com/rvandenberge/Framework/blob/master/vendor/framework/lib/Framework/DependencyInjection/ServiceLoader.php#L22) stel ik toch de service in? Hmm, dan heb ik het toch niet helemaal onder de knie.
Het enige wat je doet is een nieuwe class aanmaken. Je injecteert daar helemaal niks in.
Wouter J op 02/02/2013 18:51:10:
Ja, dat is dependency injection!
Quote:
Mag dat gewoon?
Ja, dat is dependency injection!
Oké, duidelijk!
Wouter J op 02/02/2013 18:51:10:
Over het algemeen is het zo dat je services/parameters op 1 plek, in bijv. een configuratie file (die abracadraba van gisteravond) oid, registreert en niet in een klasse.
Quote:
stel dat je in een of andere class zit en je wil van daaruit iets in de container stoppen, hoe haal je die Container dan op?
Over het algemeen is het zo dat je services/parameters op 1 plek, in bijv. een configuratie file (die abracadraba van gisteravond) oid, registreert en niet in een klasse.
Ik meen me te herinneren dat jij wel eens in zo'n container een functie stopte die dan een class returnt.
Eerst stopte je er dan bijv. de database parameters in, en vervolgens een functie die die parameters weer gebruikte. Maar bedoel je nu dat je eigenlijk al die functies in een config betstand moet zetten?
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class SecurityServiceProvider
{
public function register(Container $container)
{
$container->set('user.class', 'User');
$container->set('user') = function ($c) {
return new $c->get('user.class')();
};
$container->set('security.context.class', 'SecurityContext');
$container->set('security.context', function ($c) {
return new $c->get('security.context')($c->get('security.context.class'));
};
}
}
// ergens in een bootstrap file
$container = new Container();
$container->register(new SecurityServiceProvider());
?>
class SecurityServiceProvider
{
public function register(Container $container)
{
$container->set('user.class', 'User');
$container->set('user') = function ($c) {
return new $c->get('user.class')();
};
$container->set('security.context.class', 'SecurityContext');
$container->set('security.context', function ($c) {
return new $c->get('security.context')($c->get('security.context.class'));
};
}
}
// ergens in een bootstrap file
$container = new Container();
$container->register(new SecurityServiceProvider());
?>
Dit zie je veel gebeuren in kleinere applicaties. Zodra je over frameworks praat gaan we het hebben over services aanmaken doormiddel van configuratie. Je hebt dan bijv. zoiets:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
parameters:
user.class: User
security.context.class: SecurityContext
services:
user:
class: %user.class%
security.context:
class: %security.context.class%
arguments: [@user]
user.class: User
security.context.class: SecurityContext
services:
user:
class: %user.class%
security.context:
class: %security.context.class%
arguments: [@user]
Wat deze configuratie doet is dat hij 2 parameters instelt en vervolgens 2 services. Hierin leggen we vast dat de `user` service gewoon een nieuwe instance van `User` is (met de % geven we parameters aan in sf2). We leggen ook vast dat de `security.context` service een nieuwe instance is van `SecurityContext` (weer met zo'n parameter) en dat hij in de constructor de `user` service meekrijgt (met @ geven we services aan in sf2).
Nu heb je in het framework een klasse die deze yaml configuratie parsed en vervolgens heb je een klasse die deze data omzet in een factory. Hij maakt dus nu die functie voor je, op basis van deze configuratie.
Thanks!