PHP Dependency Injection Container selber bauen | PHP Tutorial

Поделиться
HTML-код
  • Опубликовано: 7 фев 2025
  • In diesem Video zeige ich dir, wie du einfach ein Dependency Injection Container in PHP erstellen kannst. Ich erkläre dir grob wozu dieser gebraucht wird und wie er im Grund funktioniert.
    Links zum Video:
    Anonyme Funktion: www.php.net/ma...
    Wiki: de.wikipedia.o...
    PHP-DI: php-di.org/
    Discord:discordapp.com...
    Weitere Themenvorschläge und/oder Kooperationen in die Kommentare.
    #php #dependency #dicontainer #dependencyinjection

Комментарии • 84

  • @VitalijMik
    @VitalijMik  5 лет назад +2

    Kannstest du anonyme Funktionen?

    • @sven2529
      @sven2529 5 лет назад +2

      Ja kannte ich von JavaScript. In PHP habe ich es nie benutzt und wusste auch nicht, dass es das gibt.

    • @VitalijMik
      @VitalijMik  5 лет назад +2

      PHP hat sogar Anonyme Klassen :D

    • @zielgruppe663
      @zielgruppe663 5 лет назад +1

      Ja, eine der besten Sachen, die bei PHP in den letzten Jahren eingeführt wurde :-)

  • @thomasdcodes
    @thomasdcodes 5 лет назад +4

    Absolut genial! Viele Dank Vitalij! Ich habe mich schon länger gefragt, wie man ein DI-Container aufbaut. Jetzt weiß ich es.

  • @ilch2.045
    @ilch2.045 5 лет назад +5

    Sehr verständlich erklärt Vitalij

    • @VitalijMik
      @VitalijMik  5 лет назад +1

      Dankeschön. gebe mir mühe :D

  • @heinrichschiller4673
    @heinrichschiller4673 4 года назад +2

    Sehr schönes Video. Ich sitze auch gerade an DI und versuche es zu verstehen. Dank deines Videos verstehe ich das langsam. Ja, bitte auch Video zu PHP-DI machen, weil ich mich damit auch auseinander setze :)

    • @VitalijMik
      @VitalijMik  4 года назад

      Kommt auf jeden Fall. ich hoffe nur dieses Jahr noch. Die Liste von Videowünschen wird immer länger und länger

  • @VeryBlackMan
    @VeryBlackMan 3 года назад +1

    Wieder mal klasse erklärt. Aufs wesentliche konzentriert und stückweise aufgebaut. Das Autowiring finde ich auch super, um sich die vielen Konfigurationen der Abhängigkeiten sparen zu können.

    • @VitalijMik
      @VitalijMik  3 года назад

      Autowire habe ich im PHP-DI Video genauer gezeigt :D

    • @VeryBlackMan
      @VeryBlackMan 3 года назад +1

      Danke dir für deine Mühe. Weiter so.

  • @NeverCodeAlone
    @NeverCodeAlone 5 лет назад +2

    Sehr schön Danke!!

    • @VitalijMik
      @VitalijMik  5 лет назад +1

      dankeschön für das Kommentar

  • @sven2529
    @sven2529 5 лет назад +6

    Und ja klar mach gerne ein Video zu PHP-DI. Du erzählst ja was wegen statischen Klassen und Methoden. Ich habe es ja am Anfang genauso gemacht wie schonmal angemerkt hast XD

  • @eins.oliver
    @eins.oliver 5 лет назад +1

    Mal wieder ein gutes Video, mach weiter so.

  • @korbendallas4164
    @korbendallas4164 5 лет назад +1

    gut erklärt!

  • @sven2529
    @sven2529 5 лет назад +2

    Ich habe noch eine Frage, warum nutzt man dieses "use" bei Minute 3:40 statt die $db Variable als parameter in function($db ) zu übergeben? Was macht dieses use überhaupt? was ist der Unterschied zu einem require oder einem include?

    • @VitalijMik
      @VitalijMik  5 лет назад

      mit dem use Statement, kannst du eine Variable von Außen in die Funktion hineinziehen. Viele nutzen zum Beispiel global und zeihen dann eine Variable von Außen in die Funktion hinein. Global kann man aber überall im Code verändern und somit alle Funktionen die auf die Variable zugreifen, dann kaputt machen.
      Mit use wird nur die aktuelle Variable in die Funktion reingeladen und diese wird dann verwendet. Das verändern der Variable von außen hat keine AUswirkung auf die Funktion. Desswegen ist use besser als global.
      Include und require bindet ja Dateien ein, das ist komplett was anderes. Mit use kannst du nur variablen einbinden.
      Parameter würde kein Sinn machen, weil du ja bei jedem Aufruf von $account()->create(); dann dem Account die DB übergeben müsstest. das willst du ja da aber nicht du willst einfach die Variable verwenden.

  • @sven2529
    @sven2529 5 лет назад +1

    Bei Minute 2:07 ist das ein Schreibfehler, du hast da statt construct, constuct stehen. Wenn das so nicht stimmt, dann würde ich das per Infobox oder sowas anzeigen.

    • @VitalijMik
      @VitalijMik  5 лет назад +3

      Wollte testen ob jemand aufpasst ;)

    • @sven2529
      @sven2529 5 лет назад +2

      @@VitalijMik Ha ich habe aufgepasst ;)

  • @sven2529
    @sven2529 5 лет назад +2

    Ich habe noch eine Frage zu der Klasse DB..
    Wo und wie hinterlegt man genau die Zugangsdaten, die man braucht um eine Verbindung zur Datenbank überhaupt erst zu erzeugen?

    • @VitalijMik
      @VitalijMik  5 лет назад

      Du könntest eine Konfigurationsdatei einbinden, die auch den Container befüllt mit den Zugangsdaten.
      Hier als Beispiel: pastebin.com/xRGygBcP

    • @sven2529
      @sven2529 5 лет назад

      @@VitalijMik Sowas wäre als Video denke ich auch eine Spannende Sache und natürlich wie so eine Konfigurationsdatei aussieht, wie diese aufgebaut ist, welches Art von Datei benutzt wird. php oder etwas anderes etc. Wo und wie legt man diese Zugangsdaten ab oder hinterlegt mehre Möglichkeiten um je nach Wunsch auf verschiedene Datenbanken über die Selbe DB Klasse zugreifen zu können.
      Ich schick dir in Discord dann mal ein Beispiel was ich meine.

    • @VitalijMik
      @VitalijMik  5 лет назад

      Naja da passiert nicht viel Magic Dahinter, einfach nur ein Array befüllen, das gehört ja schon zu den Grundlagen der Sprache

    • @sven2529
      @sven2529 5 лет назад

      @@VitalijMik Bedeutet die Konfigurationsdatei ist eine nur eine .php Datei mit einem oder mehrere Arrays?
      So zum Beispiel?
      file: dbconfig.php
      __________________________________
      $conn1 = [
      "host" => "beispiel.host.de,
      "
      "database" => "sampledb",
      "user" => "testuser",
      "pass" => "test123"
      ];
      $conn1 = [
      "host" => "sample.host.com",
      "database" => "testdb",
      "user" => "sampleuser",
      "pass" => "password123"
      ];
      ____________________________________
      diese wird dann in der Classe DB
      per require_once eingebunden als Variable oder wie meinst du das? Sorry wenn du sagst, dass es nicht viel magic ist, aber möchte immer alles ganz genau Wissen und auch verstehen warum man dieses oder jenes nicht macht oder eben macht.
      Ich hoffe ich gehe dir damit nicht auf die Nerven

    • @VitalijMik
      @VitalijMik  5 лет назад

      Teste den Code aus, du wirst sehen dass das kein Sinn macht, du überschreibst das Array. Probier es doch einfach aus ;)

  • @alivesurvive471
    @alivesurvive471 4 года назад

    Moin, danke fürs hilfreiche Tutorial.
    Ich verstehe leider noch nicht, wie ich die anonyme $container Funktion überall verwenden kann. Ich benötige zum einen die DB connection in der index.php (global scope) und zum anderen in einer Controller Klasse. In der index.php ganz oben vom Code erstelle ich normalerweise die db connection und führe ein paar Sachen aus. Ist das "verboten"? :D
    Das Problem hierbei wäre ja, dass wenn ich die $container Funktion global deklariere, sie für Controller Klasse unbekannt ist.

    • @VitalijMik
      @VitalijMik  4 года назад +1

      Dein Controller der muss auch in den container, die idee ist dass du keine Klassen mehr erzeugst sondern die Konfigurierst und die aus dem Container ziehst.
      Hier ein pseudocode
      pastebin.com/ciuLnkHd
      Deine Controller klasse muss schon auch im Container sein, alles muss im Container sein und du holst die einzelnen Klassen nur aus dem Container heraus

    • @alivesurvive471
      @alivesurvive471 4 года назад +1

      @@VitalijMik Achsooo jetzt wird mir einiges klar. :)
      Danke dir vielmals für deine schnelle Hilfe! Bin richtig motiviert, das gleich mal auszutesten.

  • @sven2529
    @sven2529 5 лет назад +3

    Mach vielleicht auch mal mehr Sprechpausen zwischen einzelnen Absätzen. Auch würde ich den Code vielleicht lieber schreiben statt ihn einzufügen. Das geht zwar schneller, hat aber auch den Nachteil meiner Ansicht nach, dass der Zuschauer erstmal sehr viel Input verarbeiten muss und nicht sieht wie es entstanden ist. Gleichzeitig den neuen Block Quellcode zu betrachten den du eingefügt hast und gleichzeitig dir aufmerksam zuhören, empfinde ich als schwierig. Wie immer soll das nur konstruktive Kritik sein. Ich schätze deine Video sehr.

    • @VitalijMik
      @VitalijMik  5 лет назад +1

      Ich habe sogar Pausen zwischen dem Gesagte, ich schneide halt alles raus

    • @sven2529
      @sven2529 5 лет назад +2

      @@VitalijMik Würde ich drinnen lassen, so hat der Zuschauer einige Sekunden Zeit das gesagte und das gesehen auf sich wirken zu lassen und zu verarbeiten.

  • @Douglas-Heffernan
    @Douglas-Heffernan 4 года назад

    Bei mir gab es eine Fehlermeldung bei folgender Schreibweise
    $db = function(){return new database();}
    Bei folgender war alles gut
    $db = function(){return new database();};
    Ist es normal, dass ich ein Semikolon setzten musste? In deinem Video ist keins.

    • @VitalijMik
      @VitalijMik  4 года назад

      ja es ist normal, ich habs ausversehen rausgeschnitten

    • @Douglas-Heffernan
      @Douglas-Heffernan 4 года назад +1

      @@VitalijMik Super. Dann hab ich ja alles richtig gemacht :)

    • @Douglas-Heffernan
      @Douglas-Heffernan 4 года назад

      @@VitalijMik Sag mal, ist es egal ob man Daten aus einer Datenbank innerhalb einer Klasse aufruft? Oder ist es besser die Daten ausserhalb einer Klasse aufzurufen und diese Daten dann an eine Klasse zu übergeben?

    • @VitalijMik
      @VitalijMik  4 года назад +1

      @@Douglas-Heffernan es ist besser in der Klasse die die Daten liest ein Objekt zu erstellen und diesen dann ausgeben. Ich habe dazu ein Video "repository pattern"

  • @alivesurvive471
    @alivesurvive471 4 года назад

    Ist es eigentlich normal, dass wenn man eine Klasse über den Container aufruft, sie immer wieder neu instanziiert wird? Meine DB Klasse wird z.B 15x bei jeden Seitenaufruf instanziiert, obwohl ich sie nur über den Container aufrufe. :(
    Ich dachte es funktioniert so, dass sie nur 1x instanziiert wird und man sie dann überall nutzen kann.

    • @VitalijMik
      @VitalijMik  4 года назад +1

      Ja das ist normal, in der Regel wenn du PHP DI usw benutzt die haben eine Singleton und eine Factory als auf Aufruf, dann kannst du diese Methoden verwenden um eine konfigurierte Klasse ausgeben.
      Du kannst aber das Schlüsselwort static in einer anonymen Funktion nutzen für einen Singleton
      pastebin.com/dVr73MW7

    • @alivesurvive471
      @alivesurvive471 4 года назад

      @@VitalijMik ich danke dir! Dein PHP DI Video habe ich mir schon angeschaut und werde das auf jeden Fall auch mal testen. Man ich muss noch so viel lernen... :)

    • @VitalijMik
      @VitalijMik  4 года назад +1

      Aristoteles hat mal gesagt "Ich weiß, dass ich nichts weiß" was implizit heißt je mehr du weißt desto mehr weißt du dass du nichts weißt ;) Mir geht es jeden Tag so :D

    • @alivesurvive471
      @alivesurvive471 4 года назад +1

      @@VitalijMik Hahaha ja ist wirklich so, kenne das auch zu gut. Je mehr ich lerne, desto bewusster wird es mir, wie wenig ich weiß.

  • @eins.oliver
    @eins.oliver 5 лет назад +2

    6:35 finde den Discord link nicht. Kannst du in mir geben?

    • @VitalijMik
      @VitalijMik  5 лет назад +1

      Ach wie dumm von mir, sorry, hab es aktualisiert

  • @sven2529
    @sven2529 5 лет назад +3

    Du hast das zwar echt gut erklärt, aber du bist manchmal etwas zu schnell. Das soll jetzt auch keine Kritik sein, vielleicht bin ich ja auch einfach nur zu langsam, weil ich müde bin XD.
    Seis drum, ich muss mir das Video öfter ansehen und pausieren und es wirklich zu verstehen. Ein keiner Tipp von mir. Schreibe doch im Quellcode mehr Kommentare als es einfach nur zu erklären, so hat der Zuschauer auch noch einen Visuellen Anker und muss sich nicht erst erinnern oder zurückspulen um nochmal zu verstehen, was was ist usw.

    • @VitalijMik
      @VitalijMik  5 лет назад +1

      Werde ich beim nächsten Mal machen, ich dachte halt immer das sei langweilig

    • @sven2529
      @sven2529 5 лет назад +2

      @@VitalijMik Ich weiß nicht wie andere das finden, aber ich empfinde das nicht als langweilig ;)

  • @korbendallas4164
    @korbendallas4164 5 лет назад +1

    Ein Tutorial zu Atom.io wäre zB auch super cool. ;)

    • @VitalijMik
      @VitalijMik  5 лет назад

      42 :D was möchtest du denn so wissen? Ist ja nur ein Editor :D

    • @korbendallas4164
      @korbendallas4164 5 лет назад

      @@VitalijMik Deinen Workflow mit Atom zB? Würde zumindest mich mal interessieren. Kann aber sein, dass ich da der Einzige bin :D

    • @VitalijMik
      @VitalijMik  5 лет назад

      Naja Beruflich arbeite ich mit PHPStorm aber mein Workflow sieht man in der Online Shop Serie :D

    • @korbendallas4164
      @korbendallas4164 5 лет назад +2

      @@VitalijMik Ok, das habe ich noch nicht gesehen. PHPStorm Workflow wäre aber zB auch mal interessant. Ich arbeite zB immer Remote, auch gerne mal mit Linux-Editoren, also recht simple gestrickt.

    • @VitalijMik
      @VitalijMik  5 лет назад +1

      Kommt sicherlich noch, wurde schon öfters gefragt

  • @Douglas-Heffernan
    @Douglas-Heffernan 4 года назад

    Kann ich mir so einen Container auch innerhalb einer Klasse includen oder macht das keinen Sinn?

    • @VitalijMik
      @VitalijMik  4 года назад

      Macht kein Sinn, du könntest den Container übergeben und in der KLasse dann es verwenden aber dann hast du ein anderes Pattern und Zwar "Service Locator" pattern, mittlerweile ist es aber eher ein Antipattern

    • @Douglas-Heffernan
      @Douglas-Heffernan 4 года назад

      @@VitalijMik Dann frage ich mich, wie ich den Container in meinen MCP-Pattern nutzen kann. :(

    • @VitalijMik
      @VitalijMik  4 года назад

      @@Douglas-Heffernan du musst in deinen Klasssen die Abhängigkeiten definieren. Der Container baut ja selbst alles zusammen, du schreibst im konsturkttor welche Klasse du brauchst und du kriegst die dann auch

    • @VitalijMik
      @VitalijMik  4 года назад

      @@Douglas-Heffernan also wenn du PHP DI beutzt. hier bei dem musst du hastl vorher alle instazen anelgen in anonymen funktonen und dann als parameter übergeben.
      So würde dein Pseudocode aussehen pastebin.com/ZRi68nK2

    • @Douglas-Heffernan
      @Douglas-Heffernan 4 года назад

      @@VitalijMik Wieder mal vielen Dank für deine großartige HIlfe und deine wertvolle Zeit :)

  • @zielgruppe663
    @zielgruppe663 5 лет назад +3

    Du sagst zwar, dass man durch die explizite Injektion die DB-Klasse nicht mehr braucht, aber das stimmt nicht. Du brauchst Du sie eben trotzdem, da Du sie ja in Deiner Klasse verwendest. Mit Interfaces könnte man das zwar noch etwas abschwächen, da man dann zumindest die Funktionalität nicht mitnehmen muss. Das Argument der Wiederverwendbarkeit durch DI finde ich nicht sehr einleuchtend.
    Stärkere Argument für einen DI-Container sind meiner Meinung nach
    * dass man eine zentrale Stelle hat, an der man einen Objekt-Graphen aufbauen kann,
    * dass man Abhängigkeiten leichter auswechseln kann (Macht sich z. B. gut beim Testen)
    Vielleicht hättest Du Interfaces an dieser Stelle oder vorher (Oder gibt es da schon ein Video?) erklären können, da damit die Austauschbarkeit erst wirklich gegeben ist.

    • @VitalijMik
      @VitalijMik  5 лет назад

      Ja du hast Recht, ich wollte da auch auf Interfaces eingehen, ich wollte im Video sagen dass wir so eine Explizite Abhängigkeit wenigstens faken können, im Gegensatz zu einer die in einer Methode verbaut ist. Interfaces wollte ich noch in einem anderen Video ansprechen.
      Es ist halt schwierig alles zu erklären auf ein Mal. Weil man ausgehen muss dass der Zuschauer das eine oder andere kennt. Aber das mit dem ersezten da wollte ich auf Tests und einer Zentralen Stellen eingehen.
      Du hast natürlich Recht. Ich wollte einfachste Wörter nehmen wie es nur geht, damit man das alles versteht.

  • @xLittlePsycho
    @xLittlePsycho 4 года назад

    Hat ein Container Array dann nicht die Folge dass die Editor IDE nicht weiß welche Klassen sich in den einzelnen Elementen des Containers befinden. So hätte man ja gar keine Vorschläge für Funktionen.

    • @VitalijMik
      @VitalijMik  4 года назад

      Intern in deinen Klassen würdest du ja das Interface abfragen und somit würdest du auch vorschläge kriegen. Man sollte ja sowieso nicht an ein Controller einen Kompletten DI Container übergeben sondern vorher alle Abhängigkeiten zusammenbauen.
      pastebin.com/d81namNB
      Der Container ist nur dazu da um eine neue Instanz einer Klasse mit deren Abhägngikeiten zu erstellen

    • @VitalijMik
      @VitalijMik  4 года назад +1

      Alternativ
      /**
      * @var $myObject PDO
      */
      $myObject = $container['foo'];
      und somit kann die IDE das auch verstehen

    • @xLittlePsycho
      @xLittlePsycho 4 года назад +1

      @@VitalijMik danke für die Antwort. Verstehe es jetzt ;)

  • @zielgruppe663
    @zielgruppe663 5 лет назад +1

    Eine zweite Sache ist noch, dass Du bei jedem Funktionsaufruf eine neue Instanz erstellst - Nicht eben praktisch. Da wäre es besser, Du hast ein Array, in dem Du die Abhängigkeiten nach dem ersten Aufruf speicherst.

    • @VitalijMik
      @VitalijMik  5 лет назад

      Ja es macht kein Sinn jedes Mal eine neue Instanz anzulegen, aber es macht auch kein Sinn ein einfaches Array als DI Container zu nutzen. PHP-DI macht das natürlich viel besser

    • @zielgruppe663
      @zielgruppe663 5 лет назад +1

      @@VitalijMik Na, da wo Du Deine anonymen Funktionen hast, könntest Du per use das Array reinziehen und dann dort benutzen. Ich finde Deinen Ansatz hier gar nicht schlecht. Lustigerweise habe ich vor einiger Zeit das mal selbst so umgesetzt -> github.com/marczahn/pragmatic-dependency-injection-in-go Ist zwar in Englisch und für Go, aber das Prinzip ist dasselbe.

    • @VitalijMik
      @VitalijMik  5 лет назад

      Ja Pimple macht das auch, da wird noch eine Klasse erstellt die ArrayAccess ableitet, damit hast du sogar dann Optcode cache drin ;)