PHP Dependency injection

Gestart doorOne2xs16 reacties102 weergaven

17 berichten · pagina 1 van 2

One2xs

Bot · Topicstarter

Berichten
93.699
Reputatie
0
Punten
1,27
Lid sinds
Laatst gezien
Hai.

Ik moet dus werken met dependency injection en ik snap er geen fuck van.
Wat is het nut ervan?
Ik gebruik nu Pimple en heb nu dit voor mn sessions:

$container = new Pimple();

$container[setSession] = $container->protect(function ($key,$value) {
    return $_SESSION[$key] = $value;
});

$container[getSession] = $container->protect(function ($key) {
    return $_SESSION[$key];
});


Een sessie maken en opvragen gaat dus zo:

$container[setSession](foo, bar);
$foo = $container[getSession](foo);


Wat is het voordeel t.o.:

$_SESSION[foo] = bar;
$foo = $_SESSION[foo];


?

Dat is toch veel makkelijker, duidelijker en korter?
0
One2xs

Bot · Topicstarter

Berichten
93.699
Reputatie
0
Punten
1,27
Lid sinds
Laatst gezien
Je gebruikt het ook verkeerd. Pimple is niet één of andere globale registry die functies kan registreren. Iedere class heeft meestal wel dependencies. Bijv. een repository class; die heeft een database object nodig. Omdat het lastig is om iedere keer een database te initializen met de juiste parameters en die vervolgens in je repository te injecteren gebruiken we een DI container. Voorbeeldje:

[COLOR= #0000BB]<?php

$di[/COLOR][COLOR= #007700]->[/COLOR]set[COLOR= #007700]([/COLOR][COLOR= #DD0000]database[/COLOR][COLOR= #007700], function()
{[/COLOR]
  [URL="http://www.php.net/return"]return[/URL] [COLOR= #007700]new[/COLOR] MySQL[COLOR= #007700]([/COLOR]xxx[COLOR= #007700]);
}[/COLOR]

?>


En nu kunnen we in onze code gewoon de db instance ophalen. Bijkomend voordeel is dat als je bijvoorbeeld wilt switchen van MySQL naar SQLite gewoon je class kan switchen (natuurlijk moet SQLite dan wel dezelfde methods hebben als MySQL, hier komen interfaces van te pas.)

Voorbeeldje met een repository:

[COLOR= #0000BB]<?php

$di[/COLOR][COLOR= #007700]->[/COLOR]set[COLOR= #007700]([/COLOR][COLOR= #DD0000]repository.user[/COLOR][COLOR= #007700], function()[/COLOR] use [COLOR= #007700]([/COLOR][COLOR= #0000BB]$di[/COLOR][COLOR= #007700]) {[/COLOR]
  [URL="http://www.php.net/return"]return[/URL] [COLOR= #007700]new[/COLOR] UserRepository[COLOR= #007700]([/COLOR][COLOR= #0000BB]$di[/COLOR][COLOR= #007700]->[/COLOR]get[COLOR= #007700]([/COLOR][COLOR= #DD0000]database[/COLOR][COLOR= #007700]));
});[/COLOR]

?>


Nu kan de UserRepository gebruik maken van de database, en hoef je niet iedere keer een user repo te initializen als je die wilt gebruiken, en, als je je DB switched zal die ook worden geswitched voor de user repo.

DI wilt eigenlijk zeggen => dependency injection, je injecteert je dependencies ergens in. Een DI container is dan een container waar je je dependencies in injecteert.

Je kan dan je container meegeven aan andere delen van je applicatie; dan doe je zoiets:

[COLOR= #0000BB]<?php[/COLOR]

[URL="http://www.php.net/class"]class[/URL] UserController extends Controller
[COLOR= #007700]{[/COLOR]
  [URL="http://www.php.net/private"]private[/URL] [COLOR= #0000BB]$users[/COLOR][COLOR= #007700];[/COLOR]

  [URL="http://www.php.net/public"]public[/URL] [COLOR= #007700]function[/COLOR] __construct[COLOR= #007700]([/COLOR]Container [COLOR= #0000BB]$container[/COLOR][COLOR= #007700])
  {[/COLOR]
    [COLOR= #0000BB]$this[/COLOR][COLOR= #007700]->[/COLOR]users [COLOR= #007700]=[/COLOR] [COLOR= #0000BB]$container[/COLOR][COLOR= #007700]->[/COLOR]get[COLOR= #007700]([/COLOR][COLOR= #DD0000]repository.user[/COLOR][COLOR= #007700]);
  }
}[/COLOR]

?>


Opgelet: dit is verkeerd! Het is de bedoeling dat je de user repo injecteert in je class, en niet heel de DI container.

[COLOR= #0000BB]<?php

$di[/COLOR][COLOR= #007700]->[/COLOR]set[COLOR= #007700]([/COLOR][COLOR= #DD0000]controller.user[/COLOR][COLOR= #007700], function()[/COLOR] use[COLOR= #007700]([/COLOR][COLOR= #0000BB]$di[/COLOR][COLOR= #007700])
{[/COLOR]
  [URL="http://www.php.net/return"]return[/URL] [COLOR= #007700]new[/COLOR] UserController[COLOR= #007700]([/COLOR][COLOR= #0000BB]$di[/COLOR][COLOR= #007700]->[/COLOR]get[COLOR= #007700]([/COLOR][COLOR= #DD0000]repository.user[/COLOR][COLOR= #007700]));
}[/COLOR]

[URL="http://www.php.net/class"]class[/URL] UserController
[COLOR= #007700]{[/COLOR]
  [URL="http://www.php.net/public"]public[/URL] [COLOR= #007700]function[/COLOR] __construct[COLOR= #007700]([/COLOR]UserRepository [COLOR= #0000BB]$users[/COLOR][COLOR= #007700]) {}
}[/COLOR]

?>


In je voorbeeld van sessie management kun je gebruiken maken van een sessie manager class; die je dan ook naar een interface kunt programmeren (sessies naar $_SESSION, een file, ...)

toevoeging op 3 december 2014, 16:45:28:
Oja; als je nog vragen hebt: stel ze.
0
One2xs

Bot · Topicstarter

Berichten
93.699
Reputatie
0
Punten
1,27
Lid sinds
Laatst gezien
Heb je een voorbeeld van een simpele sessie manager class?
Dan kan ik kijken of ik dat een beetje begrijp.
Als voorbeeld hoe een class opgebouwd hoort te worden.
0
One2xs

Bot · Topicstarter

Berichten
93.699
Reputatie
0
Punten
1,27
Lid sinds
Laatst gezien
570 regels samen die 2 bestanden.
En waarom kan je in een class dan niet $_SESSION[key] gebruiken?

toevoeging op 3 december 2014, 17:00:43:
Want dat is 1 regel.
569 regels minder.
+ de regels van zon hele di class

toevoeging op 3 december 2014, 17:01:28:
En als je je data in één bestand flikkert. Bootstrap.php ofzo, of include.php en daar flikker je alles in blablabla
Dan is het overzichtelijk én je kan het overal gebruiken en je voert het ook maar 1 keer in.
0
One2xs

Bot · Topicstarter

Berichten
93.699
Reputatie
0
Punten
1,27
Lid sinds
Laatst gezien
Je gebruikt niet zomaar $_SESSION omdat je later misschien wilt veranderen van storage.

Quote:
Want dat is 1 regel.
569 regels minder.
+ de regels van zon hele di class

Beetje debiele manier van nadenken. Aantal lijnen boeit niet. Het gaat om hoe flexibel het is, daarom wordt ook Symfony ook door zoveel mensen gebruikt.

toevoeging op 3 december 2014, 17:02:36:

Quote:
En als je je data in één bestand flikkert. Bootstrap.php ofzo, of include.php en daar flikker je alles in blablabla
Dan is het overzichtelijk én je kan het overal gebruiken en je voert het ook maar 1 keer in.

En zo word geen enkele moderne applicatie nog gemaakt. Je maakt gebruik van frameworks, libraries die dat allemaal handlen.
0
One2xs

Bot · Topicstarter

Berichten
93.699
Reputatie
0
Punten
1,27
Lid sinds
Laatst gezien
Komt omdat het een interface is. Ergens anders in de code word die interface ook daadwerkelijk geïmplementeerd, ik weet niet waar, ben niet echt thuis in de code van Symfony.

Vergeet heel het Symfony gebeuren, zo kan het ook:

[COLOR= #0000BB]<?php[/COLOR]

interface SessionManagerInterface [COLOR= #007700]{[/COLOR]
  [URL="http://www.php.net/public"]public[/URL] [COLOR= #007700]function[/COLOR] get[COLOR= #007700]([/COLOR][COLOR= #0000BB]$key[/COLOR][COLOR= #007700]);[/COLOR]

  [URL="http://www.php.net/public"]public[/URL] [COLOR= #007700]function[/COLOR] set[COLOR= #007700]([/COLOR][COLOR= #0000BB]$key[/COLOR][COLOR= #007700],[/COLOR] [COLOR= #0000BB]$value[/COLOR][COLOR= #007700]);
}[/COLOR]

[URL="http://www.php.net/class"]class[/URL] NativeSessionManager implements SessionManagerInterface [COLOR= #007700]{[/COLOR]
  [URL="http://www.php.net/public"]public[/URL] [COLOR= #007700]function[/COLOR] __construct[COLOR= #007700]() {[/COLOR] [URL="http://www.php.net/session_start"]session_start[/URL][COLOR= #007700](); }[/COLOR]

  [URL="http://www.php.net/public"]public[/URL] [COLOR= #007700]function[/COLOR] get[COLOR= #007700]([/COLOR][COLOR= #0000BB]$key[/COLOR][COLOR= #007700]) {[/COLOR] [URL="http://www.php.net/return"]return[/URL] [COLOR= #0000BB]$_SESSION[/COLOR][COLOR= #007700][[/COLOR][COLOR= #0000BB]$key[/COLOR][COLOR= #007700]]; }[/COLOR]

  [URL="http://www.php.net/public"]public[/URL] [COLOR= #007700]function[/COLOR] set[COLOR= #007700]([/COLOR][COLOR= #0000BB]$key[/COLOR][COLOR= #007700],[/COLOR] [COLOR= #0000BB]$value[/COLOR][COLOR= #007700]) {[/COLOR] [COLOR= #0000BB]$_SESSION[/COLOR][COLOR= #007700][[/COLOR][COLOR= #0000BB]$key[/COLOR][COLOR= #007700]] =[/COLOR] [COLOR= #0000BB]$value[/COLOR][COLOR= #007700]; }
}[/COLOR]

?>
0
One2xs

Bot · Topicstarter

Berichten
93.699
Reputatie
0
Punten
1,27
Lid sinds
Laatst gezien
Pfoe. Ik ben echt niet meer thuis in PHP.
Wat ingewikkeld allemaal sadley
0
One2xs

Bot · Topicstarter

Berichten
93.699
Reputatie
0
Punten
1,27
Lid sinds
Laatst gezien
Heb je mijn voorbeeldje ^ gezien? Die is simpel.
0
One2xs

Bot · Topicstarter

Berichten
93.699
Reputatie
0
Punten
1,27
Lid sinds
Laatst gezien
Oke dat is ongeveer zoals ik het nu heb?

toevoeging op 3 december 2014, 17:07:00:
Alleen heb ik die functies in Pimple geflikkerd en niet in een eigen class
0
One2xs

Bot · Topicstarter

Berichten
93.699
Reputatie
0
Punten
1,27
Lid sinds
Laatst gezien
Mooi dan. Je wou weten wat het nut van een DI container was, ik heb je het uitgelegd.
0
One2xs

Bot · Topicstarter

Berichten
93.699
Reputatie
0
Punten
1,27
Lid sinds
Laatst gezien
Is iets duidelijker in ieder geval, thanks.

toevoeging op 3 december 2014, 17:20:50:
Maar moet ik die class dan in Pimple gooien?
Want nu moet ik voor alles wat ik doe zon module aanmaken en alsnog aanroepen.
Doesnt make sense.

Wel als ik deze class nu in Pimple kan laden en door alleen $container = new Pimple(); te doen ik met $container->setSession(); bijvoorbeeld sessies kan aanmaken.
0
One2xs

Bot · Topicstarter

Berichten
93.699
Reputatie
0
Punten
1,27
Lid sinds
Laatst gezien
Ik ga vandaag weer verder en loop al direct tegen een probleem aan:
Dit is mijn code nu:

[COLOR= #0000BB]<?php 
$container[/COLOR] [COLOR= #007700]= new[/COLOR] Pimple[COLOR= #007700]();[/COLOR]

interface SessionManagerInterface [COLOR= #007700]{[/COLOR]
  [URL="http://www.php.net/public"]public[/URL] [COLOR= #007700]function[/COLOR] get[COLOR= #007700]([/COLOR][COLOR= #0000BB]$key[/COLOR][COLOR= #007700]);[/COLOR]

  [URL="http://www.php.net/public"]public[/URL] [COLOR= #007700]function[/COLOR] set[COLOR= #007700]([/COLOR][COLOR= #0000BB]$key[/COLOR][COLOR= #007700],[/COLOR] [COLOR= #0000BB]$value[/COLOR][COLOR= #007700]);
}[/COLOR]

[URL="http://www.php.net/class"]class[/URL] NativeSessionManager implements SessionManagerInterface [COLOR= #007700]{[/COLOR]
  [URL="http://www.php.net/public"]public[/URL] [COLOR= #007700]function[/COLOR] __construct[COLOR= #007700]() {[/COLOR] [URL="http://www.php.net/session_start"]session_start[/URL][COLOR= #007700](); }[/COLOR]

  [URL="http://www.php.net/public"]public[/URL] [COLOR= #007700]function[/COLOR] get[COLOR= #007700]([/COLOR][COLOR= #0000BB]$key[/COLOR][COLOR= #007700]) {[/COLOR] [URL="http://www.php.net/return"]return[/URL] [COLOR= #0000BB]$_SESSION[/COLOR][COLOR= #007700][[/COLOR][COLOR= #0000BB]$key[/COLOR][COLOR= #007700]]; }[/COLOR]

  [URL="http://www.php.net/public"]public[/URL] [COLOR= #007700]function[/COLOR] set[COLOR= #007700]([/COLOR][COLOR= #0000BB]$key[/COLOR][COLOR= #007700],[/COLOR] [COLOR= #0000BB]$value[/COLOR][COLOR= #007700]) {[/COLOR] [COLOR= #0000BB]$_SESSION[/COLOR][COLOR= #007700][[/COLOR][COLOR= #0000BB]$key[/COLOR][COLOR= #007700]] =[/COLOR] [COLOR= #0000BB]$value[/COLOR][COLOR= #007700]; }
}[/COLOR]

[COLOR= #0000BB]$container[/COLOR][COLOR= #007700][[/COLOR][COLOR= #DD0000]sessionManager[/COLOR][COLOR= #007700]] =[/COLOR] [COLOR= #0000BB]$sessionManager[/COLOR] [COLOR= #007700]= new[/COLOR] NativeSessionManager[COLOR= #007700]();[/COLOR]

[COLOR= #0000BB]$container[/COLOR][COLOR= #007700][[/COLOR][COLOR= #DD0000]setSession[/COLOR][COLOR= #007700]] =[/COLOR] [COLOR= #0000BB]$container[/COLOR][COLOR= #007700]->[/COLOR]protect[COLOR= #007700](function ([/COLOR][COLOR= #0000BB]$key[/COLOR][COLOR= #007700],[/COLOR][COLOR= #0000BB]$value[/COLOR][COLOR= #007700]) {[/COLOR]
    [URL="http://www.php.net/return"]return[/URL] [COLOR= #0000BB]$container[/COLOR][COLOR= #007700][[/COLOR][COLOR= #DD0000]sessionManager[/COLOR][COLOR= #007700]]->[/COLOR]set[COLOR= #007700]([/COLOR][COLOR= #0000BB]$key[/COLOR][COLOR= #007700],[/COLOR] [COLOR= #0000BB]$value[/COLOR][COLOR= #007700]);
});[/COLOR]

[COLOR= #0000BB]$container[/COLOR][COLOR= #007700][[/COLOR][COLOR= #DD0000]getSession[/COLOR][COLOR= #007700]] = function ([/COLOR][COLOR= #0000BB]$key[/COLOR][COLOR= #007700]) {[/COLOR]
    [URL="http://www.php.net/return"]return[/URL] [COLOR= #0000BB]$container[/COLOR][COLOR= #007700][[/COLOR][COLOR= #DD0000]sessionManager[/COLOR][COLOR= #007700]]->[/COLOR]get[COLOR= #007700]([/COLOR][COLOR= #0000BB]$key[/COLOR][COLOR= #007700]);
};[/COLOR]

[COLOR= #0000BB]$container[/COLOR][COLOR= #007700][[/COLOR][COLOR= #DD0000]setSession[/COLOR][COLOR= #007700]]([/COLOR][COLOR= #DD0000]test_cookie[/COLOR][COLOR= #007700],[/COLOR] [COLOR= #DD0000]Goodbye world![/COLOR][COLOR= #007700]);[/COLOR]

[URL="http://www.php.net/echo"]echo[/URL] [COLOR= #0000BB]$container[/COLOR][COLOR= #007700][[/COLOR][COLOR= #DD0000]getSession[/COLOR][COLOR= #007700]]([/COLOR][COLOR= #DD0000]test_cookie[/COLOR][COLOR= #007700]);[/COLOR]


En deze errors krijg ik:

Notice: Undefined variable: container 
Fatal error: Call to a member function set() on a non-object


Het gaat om dependency injection, maar ik heb al meer dan een jaar niets meer met php gedaan en daarvoor heb ik nog nooit in php met dependency injection gewerkt.
Dus heb geen idee hoe het in elkaar steekt.

toevoeging op 11 december 2014, 13:38:01:
Die session class, moet ik die helemaal in Pimple stampen of moet ik die in een nieuw bestand als normale class opslaan?
En dan includen op dezelfde pagina waar ik Pimple start en hem dan in Pimple laden?

Want dan snap ik weeral het nut niet van een dependency container sadley (als je toch die hele waslijst met includes behoudt)
0

Jouw reactie

Deel je idee, stel een vraag of help een ander verder.

Editor laden…

Praat mee met de One2xs-community.

Inloggen om te reageren