Ankündigung

Einklappen
Keine Ankündigung bisher.

Front Controller- Router

Einklappen

Neue Werbung 2019

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

  • #31
    PHP-Code:
    $fooAction = function(RequestContract $requestRoutePropertyContract $route)
    {
        
    $something $this->service('something',['foo' => 12345'bar' => 'baz']);
        
    $something->send($request->get('that'null), $route->get('id'));
        
        return 
    $this->response($this->service('twig')->render('foo.twig'$something->getResult()));
    };

    $actionFacade $someDIC->make(ActionFacade::class);
    $concreteAction $fooAction->bindTo($actionFacade);

    $someDIC->call($concreteAction); 
    Woher soll $someDIC wissen welche Route er der ActionClosure übergeben soll und wieso sollte ein DIC für Routingaufgaben zuständig sein?

    vg
    jack
    -

    Kommentar


    • #32
      Ist er nicht, Service-Extension durch den Dispatcher, before-hook, ...
      [URL="https://gitter.im/php-de/chat?utm_source=share-link&utm_medium=link&utm_campaign=share-link"]PHP.de Gitter.im Chat[/URL] - [URL="https://raindrop.io/user/32178"]Meine öffentlichen Bookmarks[/URL] ← Ich habe dir geholfen ? [B][URL="https://www.amazon.de/gp/wishlist/348FHGUZWTNL0"]Beschenk mich[/URL][/B].

      Kommentar


      • #33
        Service-Extension durch den Dispatcher, before-hook, ...
        das ist - zumindest für mich - leider nicht nachvollziehbar. $concreteAction wird an $DIC->call() übergeben und kann somit erst innerhalb von call() mit den richtigen Argumenten aufgerufen werden. Was passiert innerhalb von call?

        vg
        jack
        -

        Kommentar


        • #34
          Dort wird anhand einer callable reflection identifiziert was übergeben werden muss und das callable aufgerufen. Mehr nicht.
          [URL="https://gitter.im/php-de/chat?utm_source=share-link&utm_medium=link&utm_campaign=share-link"]PHP.de Gitter.im Chat[/URL] - [URL="https://raindrop.io/user/32178"]Meine öffentlichen Bookmarks[/URL] ← Ich habe dir geholfen ? [B][URL="https://www.amazon.de/gp/wishlist/348FHGUZWTNL0"]Beschenk mich[/URL][/B].

          Kommentar


          • #35
            ok, aber die richtige Route läßt sich nicht einfach mit einer "callable reflection" identifizieren, wo passiert also das matching der Route?

            vg
            jack
            -

            Kommentar


            • #36
              Durch den Dispatcher, der den RoutePropertyContract im Service Container konfiguriert. Alternativ eine Factory die hinter dem RoutePropertyContract im Service Container konfiguriert ist und das Request-Objekt beim Router abfragt und entsprechend die RouteProperties vom Router zu der Aktuellen Route anfordert.

              Kommt ganz darauf an wie eng oder intelligent das Auto-wiring verknüpft ist.
              [URL="https://gitter.im/php-de/chat?utm_source=share-link&utm_medium=link&utm_campaign=share-link"]PHP.de Gitter.im Chat[/URL] - [URL="https://raindrop.io/user/32178"]Meine öffentlichen Bookmarks[/URL] ← Ich habe dir geholfen ? [B][URL="https://www.amazon.de/gp/wishlist/348FHGUZWTNL0"]Beschenk mich[/URL][/B].

              Kommentar


              • #37
                ok, ist soweit klar.

                Wobei ersteres

                Durch den Dispatcher, der den RoutePropertyContract im Service Container konfiguriert.
                zu einer unschönen und überflüssigen Abhängigkeit zwischen dem Dispatcher und DIC führen würde.

                Beide Alternativen setzen offensichtlich den Request als Service voraus. Das wird spätestens dann zu einem Problem wenn man intern mit Subrequests weiterarbeiten will. Deshalb würde ich den Request besser nicht in einen DIC packen.

                vg
                jack
                -

                Kommentar


                • #38
                  Zitat von jack88 Beitrag anzeigen
                  ok, ist soweit klar.

                  Wobei ersteres



                  zu einer unschönen und überflüssigen Abhängigkeit zwischen dem Dispatcher und DIC führen würde.

                  Beide Alternativen setzen offensichtlich den Request als Service voraus. Das wird spätestens dann zu einem Problem wenn man intern mit Subrequests weiterarbeiten will. Deshalb würde ich den Request besser nicht in einen DIC packen.

                  vg
                  jack
                  Chainable Requests.
                  [URL="https://gitter.im/php-de/chat?utm_source=share-link&utm_medium=link&utm_campaign=share-link"]PHP.de Gitter.im Chat[/URL] - [URL="https://raindrop.io/user/32178"]Meine öffentlichen Bookmarks[/URL] ← Ich habe dir geholfen ? [B][URL="https://www.amazon.de/gp/wishlist/348FHGUZWTNL0"]Beschenk mich[/URL][/B].

                  Kommentar


                  • #39
                    Chainable Requests...?
                    -

                    Kommentar


                    • #40
                      Leute, das ist Kindergarten.

                      Zitat von Carpenter Beitrag anzeigen
                      Irgendwie verstoßen Controller doch dann auch gegen solid oder? Sie haben für mich dann mehrere Kompetenzen, wenn sie mehrere Actions beinhalten.
                      Nicht, wenn die einzige Aufgabe eines Controllers ist, Aufgaben an andere Komponenten zu verteilen. Das ist ja auch die tatsächliche Bedeutung eines Controllers:

                      Zitat von Ralf Westphal on single responsibility principle
                      A functional unit on a given level of abstraction should only be responsible for a single aspect of a system’s requirements. An aspect of requirements is a trait or property of requirements, which can change independently of other aspects.

                      Kommentar


                      • #41
                        Zitat von lottikarotti Beitrag anzeigen
                        Hallöchen,

                        da meine Controller-Methoden ebenfalls automatisiert mit Abhängigkeiten gefüttert werden, kann ich diese in Einzelfällen auch dort angeben wo ich sie brauche:
                        Wie genau löst du die Abhängigkeiten auf Methodenebene eigentlich auf?
                        Kannst du mir dazu bitte ein kurzes Pseudocode Beispiel schreiben?

                        Viele Grüße
                        Carpenter

                        Kommentar


                        • #42
                          Hallöchen,

                          Zitat von Carpenter Beitrag anzeigen
                          Wie genau löst du die Abhängigkeiten auf Methodenebene eigentlich auf?
                          Kannst du mir dazu bitte ein kurzes Pseudocode Beispiel schreiben?
                          Klar doch. Da es zum eigentlichen Thema des Threads beiträgt, habe ich mal den groben Ablauf skizziert und kommentiert. In der Praxis ist das natürlich ein wenig komplexer (bspw. können ID-Parameter direkt in ein User-Objekt konvertieren, Errors werden abgefangen, usw.), aber ich denke die Richtung wird mit diesem Beispiel ganz gut deutlich:

                          PHP-Code:
                          <?php

                          /**
                           * Hier werden die Routen festgelegt. Dieser Part kann alternativ in
                           * eine externe Konfigurations-Datei ausgelagert werden.
                           */
                          $routes = new Routes();

                          // Das Container-Objekt für die Routen kann wie ein Array angesprochen werden.
                          $routes['GET /users'] = [
                              
                          'controller' => [UserController::class, 'findAll'],
                              
                          'format' => 'json'
                          ];
                          $routes['GET /users/{id:int}'] = [
                              
                          'controller' => [UserController::class, 'findOne'],
                              
                          'format' => 'json'
                          ];
                          $routes['POST /users'] = [
                              
                          'controller' => [UserController::class, 'store'],
                              
                          'format' => 'json'
                          ];
                          $routes['POST /users/{id:int}'] = [
                              
                          'controller' => [UserController::class, 'update'],
                              
                          'format' => 'json'
                          ];
                          $routes['DELETE /users/{id:int}'] = [
                              
                          'controller' => [UserController::class, 'remove'],
                              
                          'format' => 'json'
                          ];

                          // Die Routen werden zu vollwertigen regulären Ausdrücken kompiliert.
                          // Dieser Vorgang lässt sich für den Produktivbetrieb ganz gut cachen.
                          $routes->compile();

                          /**
                           * An dieser Stelle wird ein Request-Objekt erzeugt. Dieses kann, je nach
                           * Kontext, auf unterschiedliche Weise bestimmt werden. Das ist u.A. dann
                           * interessant, wenn man CLI-Aufrufe o.ä. supporten will.
                           */
                          $request = new HttpRequest;

                          /**
                           * Der URI wird im Normalfall aus dem Request-Objekt generiert.
                           */
                          $uri implode(' ', [
                              
                          $request->getMethod(),
                              
                          $request->getUri()
                          ]);

                          /**
                           * Der Matcher sucht sich die Route heraus, deren Pattern mit einer der
                           * konfigurierten Routen übereinstimmt und liefert diese anschließend zurück.
                           * Dabei werden alle Parameter, welche innerhalb der Route definiert wurden
                           * (bspw. eine Id) in die Variable `$params` geschrieben.
                           */
                          $matcher = new UrlMatcher;
                          $route $matcher->match($uri$routes$params);

                          /**
                           * An dieser Stelle wird der DI-Container geladen und konfiguriert.
                           */
                          $dic = new DIC;
                          $dic->alias('My\Repository\UserRepositoryInterface''My\Repository\SQLUserRepository');
                          foreach(
                          $params as $key => $param){
                              
                          $dic->value($key$value);
                          }

                          /**
                           * Anhand der ermittelten Route wird nun ein Controller-Objekt erzeugt, dessen
                           * Abhängigkeiten automatisiert über den DI-Container aufgelöst werden. Dieser
                           * Step kümmert sich also um die Constructor-Injection.
                           */
                          list($class$method) = $route['controller'];
                          $controller $dic->make($class);

                          /**
                           * Da sowohl Controller-Objekt erzeugt als auch die Ziel-Methode bekannt sind,
                           * wird über den DI-Container die Methode aufgerufen. Dieser löst erneut
                           * die Abhängigkeiten automatisiert auf. Auch GET- bzw. POST-Daten können
                           * über deren Parameternamen direkt injiziert werden.
                           */
                          $response $dic->invoke($controller$method);

                          /**
                           * Zu guter letzt wird das Resultat des Controllers, abhängig von der
                           * Routen-Konfiguration, formatiert und entsprechend ausgeliefert.
                           */
                          $responseTransformer = new ResponseTransformer;
                          $response $responseTransformer->transform($response$route['format'], $headers);
                          foreach(
                          $headers as $header){
                              
                          header($header);
                          }
                          echo 
                          $response;
                          Ich erhebe natürlich keinerlei Anspruch darauf, dass das die beste Lösung ist, aber für die meisten meiner kleinen-mittleren Projekte hat sich diese Vorgehensweise bewährt und reicht vollkommen aus. Die verwendeten Komponenten sind in Eigenentwicklung entstanden.

                          Viele Grüße,
                          lotti
                          [SIZE="1"]Atwood's Law: any application that can be written in JavaScript, will eventually be written in JavaScript.[/SIZE]

                          Kommentar


                          • #43
                            Exakt so* mache ich das auch. Interessant.

                            * Routing erzeugt Parameter > Parameter beschreiben Controller und zu startende Methode > Rückgabe wird an Renderer übergeben, der in den Parametern spezifiziert wird.

                            Kommentar

                            Lädt...
                            X