Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] Dependency Injection in einen Controller. Wo mache ich das?

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [Erledigt] Dependency Injection in einen Controller. Wo mache ich das?

    Hallo zusammen,

    ich habe eine Frage, die (noch) nicht konkret mit einem Softwareprojekt zu tun hat. Geht eher Richtung Software-Design / Architektur.

    Man nehme mal an, wir haben Controller die gewissen Abhängigkeiten. Um es besser testbar zu machen sollen die aber nicht im Controller erstellt werden, sondern von außen abgespritzt (... hä??? nein, natürlich 'injiziert' - abspritzen war nur der erste Treffer bei leo ) werden.

    Beispiel:

    PHP-Code:
    class UserController extends SomeAbstractController 
    {
        protected 
    $mapper;
        
        public function 
    __construct(UserMapper $mapper)
        {
            
    $this->mapper $mapper;
        }    

    So weit, so gut. Aber wo erstelle ich so ein UserMapper Objekt um es dann injizieren zu können? Wenn ich an das Zend Framework denke (andere kenne ich nicht wirklich), dann werden mir die Controller Instanzen durch den Dispatcher in irgendeiner Form erstellt. Da habe ich nämlich - soweit ich weiß - keine Möglichkeit dieser Form von DI.
    Wenn ich aber etwas eigenes schreibe, was wäre eine geeignete Stelle ohne dabei aber auf Flexibilität beim Erstellen von anderen Controllern verzichten zu müssen?

    Ich hab das jetzt einfach mal so runter geschrieben. Möglicher Weise sagt ihr jetzt, dass das so einfach gar nicht zu entscheiden ist und man sich im Vorfeld noch viel mehr Gedanken über die Architektur machen müsste. Wäre für mich auch ok, dann müsste ich das ein Stück weit nach hinten stellen, mir kam dieser Gedanke nur mal so. Eventuell hat aber jemand hier eine konkrete Ahnung / Idee, wie man das in ein paar Sätzen vorstellen kann.
    [I]Es ist schon alles gesagt! Nur noch nicht von allen! (Karl Valentin)[/I]
    [I]Wenn du eine weise Antwort verlangst, musst du vernünftig fragen. (Johann Wolfgang von Goethe)[/I]

  • #2
    sondern von außen abgespritzt (... hä??? nein, natürlich 'injiziert' - abspritzen war nur der erste Treffer bei leo ) werden.
    Kannst Du uns allen so einen Mist einfach ersparen?

    Sinnvollerweise erzeugt man die Objekte dort, wo auch die Controllerinstanz erzeugt wird.
    [COLOR="#F5F5FF"]--[/COLOR]
    [COLOR="Gray"][SIZE="6"][FONT="Georgia"][B]^^ O.O[/B][/FONT] [/SIZE]
    „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
    [URL="http://www.php.de/javascript-ajax-und-mehr/107400-draggable-sorttable-setattribute.html#post788799"][B]Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“[/B][/URL][/COLOR]
    [COLOR="#F5F5FF"]
    --[/COLOR]

    Kommentar


    • #3
      Zitat von nikosch Beitrag anzeigen
      Kannst Du uns allen so einen Mist einfach ersparen?
      Uhhhh.... verzeiht mir oh' Herr...

      Zum sachlichen (PS: jetzt wo ich das schreibe... naja, o.g. ist auch nicht gerade sachlich... Aber Ausdruck und Form... egal jetzt):
      Zitat von nikosch Beitrag anzeigen
      Sinnvollerweise erzeugt man die Objekte dort, wo auch die Controllerinstanz erzeugt wird.
      Ich habe z.B. eine index.php in der ich aus den Requests ermittel, welcher Controller instanziiert werden soll. Dafür könnte ich mir einen Router behauen oder im trivialen Fall einfach die Request-Variablen abfangen und so etwas in dieser Art anstellen:

      PHP-Code:
      try {
          
      $controller = isset( $_REQUEST['controller'] ) ? $_REQUEST['controller'] : 'Index';
          
      $controllername APP_NAMESPACE '\\Controller\\' $controller

          if ( 
      file_exists(APPLICATION_PATH '/library/' $controllername '.php') ) {
              require_once 
      $controllername '.php';
              
              
      /*
               * @var $controller \Citkomm\Controller\AbstractConstroller
               */
              
      $controller = new $controllername;
              
      $controller->handle();
          } else {
              throw new \
      Controller\ControllerException('Controller does not exist');
          }
          
      } catch 
      /* Exceptions... */ 
      So ein Controller erbt dann immer von einem abstrakten Controller und kennt eben die Methode handle().

      PHP-Code:
      public function handle()
          {
              
      $action = isset($_REQUEST['action'])? $_REQUEST['action'] : 'index';
              
      $actionMethod $action 'Action';
              
              if ( !
      method_exists($this$actionMethod) ) {
                  throw new 
      UnknownActionException('Action ' $action ' is unknown');
              }
              
              
      //Call the action
              
      $this->$actionMethod();
              
              
      $class substr(
                              
      get_class($this),
                              
      strrpos(get_class($this), '\\') + 1  
              
      );
              
              
      $viewScript $this->getViewPath() . '/' $class '/' $action '.phtml';
              
              if ( 
      $this->viewEnabled && file_exists$viewScript ) ) {
                  @include 
      $this->getViewPath() . '/layout/html_head.phtml';
                  include 
      $viewScript;
                  @include 
      $this->getViewPath() . '/layout/html_foot.phtml';
              }
          } 
      Grundsätzlich funktioniert das. Irgendwie ist das ganze aber nur halb durchdacht. Denn: Wenn ich automatisch entscheide, dass es sich um einen UserController handelt, woher soll ich dann wissen, dass da konkrete Abhängikeiten injiziert werden sollen.

      Das ganze kommt aus einer kleinen Anwendung, wo ich mich versucht habe darum zu kümmern, die einzelnen Komponenten etwas zu entkoppeln. Mir kommt aber immer mehr und mehr der Verdacht, dass mir das gar nicht so gelungen ist. Bzw. dass es noch deutlich Optimierungsbedarf gibt.
      [I]Es ist schon alles gesagt! Nur noch nicht von allen! (Karl Valentin)[/I]
      [I]Wenn du eine weise Antwort verlangst, musst du vernünftig fragen. (Johann Wolfgang von Goethe)[/I]

      Kommentar


      • #4
        schau dir mal diesen Code an, vielleicht kriegste denkanstöße

        https://github.com/synapsestudios/kohana-dependencies
        apt-get install npm -> npm install -g bower -> bower install <package> YOLO [URL]https://www.paypal.me/BlackScorp[/URL] | Mein Youtube PHP Kanal: [url]https://www.youtube.com/c/VitalijMik[/url]

        Kommentar


        • #5
          Das Problem ist in der Tat, zu ermitteln, welche Abhängigkeiten dem Controller injiziert werden müssen. Solange die Applikation noch überschaubar ist, bieten sich hierfür Constructor bzw. Setter bzw. Property Injection an. Was das genau alles ist, kannst du hier nachlesen: http://components.symfony-project.or...ency-Injection.

          Mit steigender Komplexität würde ich mich an deiner Stelle nach Dependency Injection Container umsehen, wie bspw. von Symfony 2: http://symfony.com/doc/current/book/...container.html.

          Kommentar


          • #6
            wenn ich das richtig seh, bedeutet "dependency injection",
            daß ein Objekt abhängig von bestimmten Faktoren erzeugt wird.

            Also z.B. daß die Art und Weise wie ein Controllerobjekt "aussieht"
            von der Anwendungskonfiguration abhängt.

            So sind z.B. verschiedene Konfigurationen für den Produktiveinsatz
            und die Entwicklungsumgebung denkbar.

            Die Frage "wo" dieses Controllerobjekt erzeugt wird stellt sich doch
            in diesem Zusammenhang gar nicht.

            Falls ich falsch liege bitte korrigieren.
            Eine if-else-Abfrage nimmt, ordentlich geschrieben eine Menge Platz weg. Platzsparend geht es mit einem ternären Operator.

            Kommentar


            • #7
              Ja, an DI Container

              edit: Irgendwie ist der Rest dieses Postings im Nirvana gelandet... Melde mich später noch mal.
              [I]Es ist schon alles gesagt! Nur noch nicht von allen! (Karl Valentin)[/I]
              [I]Wenn du eine weise Antwort verlangst, musst du vernünftig fragen. (Johann Wolfgang von Goethe)[/I]

              Kommentar


              • #8
                Wenn du keinen IoC Container benutzen willst und nur eine Stelle außerhalb des Front Controller/Router/Action Controller Komplexes suchst, wo die Controller mit ihren jeweiligen Abhängigkeiten versorgt werden, bietet sich vllt. auch das (Abstract)* Factory Pattern an. In der Factory werden die Controller dann erzeugt und ggf. abhängig von äußeren Faktoren konfiguriert.

                PHP-Code:
                // anstatt: $controller = new $controllername
                $factory = new ControllerFactoryImplementation();
                $controller $factory->createController($controllername); 
                *) Abstract Factory würde bedeuten dass es verschiedene Implementierungen der ControllerFactory für unterschiedliche Zwecke geben kann.
                [IMG]https://g.twimg.com/twitter-bird-16x16.png[/IMG][URL="https://twitter.com/fschmengler"]@fschmengler[/URL] - [IMG]https://i.stack.imgur.com/qh235.png[/IMG][URL="https://stackoverflow.com/users/664108/fschmengler"]@fschmengler[/URL] - [IMG]http://i.imgur.com/ZEqflLv.png[/IMG] [URL="https://github.com/schmengler/"]@schmengler[/URL]
                [URL="http://www.schmengler-se.de/"]PHP Blog[/URL] - [URL="http://www.schmengler-se.de/magento-entwicklung/"]Magento Entwicklung[/URL] - [URL="http://www.css3d.net/"]CSS Ribbon Generator[/URL]

                Kommentar


                • #9
                  Jau fab, dieser Gedanke ist mir vorhin zwischendurch auch gekommen.

                  Könnte in der Tat der korrekte Weg sein, wenn man DI Container vermeiden möchte (was bei mir jetzt nicht zwingend der Fall ist). Für den ersten Teil ist das hier erstmal erledigt. Würde mich natürlich freuen, wenn sich trotzdem noch welche melden, wenn sie Tipps und Anregungen haben. Danke soweit!
                  [I]Es ist schon alles gesagt! Nur noch nicht von allen! (Karl Valentin)[/I]
                  [I]Wenn du eine weise Antwort verlangst, musst du vernünftig fragen. (Johann Wolfgang von Goethe)[/I]

                  Kommentar


                  • #10
                    ich baue atm. auch intensiv meinen aus:
                    http://anydi.ainfach.de/

                    ist ein relativ alternativer Ansatz, aber sicher einen Blick wert. Derzeit entwickel ich intensiv daran, die Verwendung noch deutlich einfacher zu machen, ohne u.a. an der code completion einzubüßen. läuft wunderbar in Kombi mit dem ZF =)

                    selbstverständlich ist alles dokumentiert und die Testabdeckung müsste bei 98%+ liegen.

                    Kommentar


                    • #11
                      Zitat von notyyy Beitrag anzeigen
                      ich baue atm. auch intensiv meinen aus:
                      http://anydi.ainfach.de/

                      ist ein relativ alternativer Ansatz, aber sicher einen Blick wert. Derzeit entwickel ich intensiv daran, die Verwendung noch deutlich einfacher zu machen, ohne u.a. an der code completion einzubüßen. läuft wunderbar in Kombi mit dem ZF =)

                      selbstverständlich ist alles dokumentiert und die Testabdeckung müsste bei 98%+ liegen.
                      Den hab ich mir auch schon angesehen
                      [I]Es ist schon alles gesagt! Nur noch nicht von allen! (Karl Valentin)[/I]
                      [I]Wenn du eine weise Antwort verlangst, musst du vernünftig fragen. (Johann Wolfgang von Goethe)[/I]

                      Kommentar


                      • #12
                        Zitat von dennis81 Beitrag anzeigen
                        Den hab ich mir auch schon angesehen
                        ich entwickel derzeit das ding relativ intensiv weiter, und freue mich natürlich immer über kritik =)

                        Kommentar

                        Lädt...
                        X