Ankündigung

Einklappen
Keine Ankündigung bisher.

Externen Komponenten den ServiceContainer zur Verfügung stellen

Einklappen

Neue Werbung 2019

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

  • Externen Komponenten den ServiceContainer zur Verfügung stellen

    Hallo,

    beim Erstellen meines Frameworks habe ich bis jetzt auf Singleton verzichtet (bis auf Factories). Auch meine ursprüngliche Überlegung, den FrontController als Singleton zu realisieren, scheiterte kläglich, als ich versucht habe HMVC-ähnliche Knoten aufzurufen. Daher wird dieser nun, wie es sich gehört, normal instanziiert.

    Hintergrund zum FC:
    Ein Request landet beim FrontController. Der FC zieht dann den Router hinzu und wertet den Request aus. Der FrontController generiert dann mit diesen Daten und mit Hilfe eines ControllerBuilders (eine Art Factory) dann den Controller. Vor dem Ausführen der eigentlichen Action übergibt sich der FrontController nochmal selbst an den Controller. Das liegt daran, dass der FrontController Objekte enthält wie Config, Request, ServiceContainer etc, auf die man im Controller stets Zugriff haben sollte.


    Ich bin so fixiert auf den FrontController, da dieser den Request, die Config, den Router oder auch den ServiceContainer (DI-Container) beinhaltet.

    Nun kommen externe Komponenten ins Spiel: Als Beispiel nehme ich mal einen Logger, der nicht fester Bestandteil des Frameworks ist. Ein Writer dieses Loggers, etwa FirePHPWriter, muss auf meinen FrontController zugreifen könne, um den ServiceContainer zu bekommen, der wiederum eine Instanz von FirePHP spendet.

    (Alternative: Der DatabaseWriter muss auf den Service 'PDO' zugreifen.)

    Als mein FC noch Singleton war, konnte ich bequem sagen
    PHP-Code:
    FrontController::getInstance()->getServiceContainer->get('FirePHP'); 
    Aber das geht ja nun nicht mehr, weil der ServiceContainer bzw. der FrontController nicht mehr global ansteuerbar ist.

    Ich habe mir gedacht, nur den ServiceContainer als Singleton zu gestalten. Dieser ServiceContainer beinhaltet dann auch den Router, die Config etc.

    Das widerspricht aber etwas meinem Prinzip, dass der ServiceContainer keine Framework-eigenen Objekte verwaltet.

    Habt ihr eine Idee?

  • #2
    Komponente generell mit Controller/ServiceContainer-Instanz instanziieren?
    [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
      Ja, mein Problem hat sich wohl erledigt. Die Config mache ich nun doch als Registry (sprich, Singleton) und externe Komponente selbst brauchen nicht auf den Service Container zuzugreifen, da sie selbst Teil des Containers sind. Diese werden dann nur im Controller angefragt.

      Kommentar


      • #4
        Ich habe das bei mir so gelöst, dass es pro Request ein "Context-Objekt" als Singleton gibt, dass alle relevanten Objekte, die man innerhalb der Applikation benötigt, enthält (Request, Response, DIC, Konfiguration, etc.). Der Aufruf gestaltet sich dann so:
        PHP-Code:
        \ZN\Application\Context::instance()->getConfiguration();
        \
        ZN\Application\Context::instance()->getDIC();
        \
        ZN\Application\Context::instance()->getRequest();
        // etc. 
        Jetzt werden wieder einige aufschreien und meckern, dass das nicht besonders sauber sei. Aber: Ich habe wirklich lange an dem Problem gesessen und wenn man HMVC so umsetzen will, wie ich das in meinem Framework (Heißt, HMVC-Knoten sollen an jeder Stelle benutzt werden können), dann MUSS man irgendwo eine zentrale Stelle haben, die alle notwendigen Informationen enthält.

        Kommentar


        • #5
          Bei uns gibt es auch einen Kontext. Nur andersrum als bei xm22. Sprich der Kontext ist eine Eigenschaft des Requests und der wird via manueller Injektion durchgeschleift.

          Kommentar


          • #6
            Sprich der Kontext ist eine Eigenschaft des Requests und der wird via manueller Injektion durchgeschleift.
            Das klingt gut. Was enthält bei euch das Kontext-Objekt?

            Kommentar


            • #7
              @xm22
              Aber bekommst du durch dein Context-Singleton keine Probleme? Wenn es einen internen Subrequest gibt, kann ZNApplicationContext doch nicht neu kreiert werden. Das bestehende Singleton wird demnach überschrieben. Somit hast du keine Kontrolle mehr über vorherige Stati, nachdem ein Subrequest ausgelöst wurde. Wie löst du das?

              Kommentar


              • #8
                Wenn es einen internen Subrequest gibt
                Das Problem stellt sich in der Tat - Allerdings ist die Wahrscheinlichkeit, dass so etwas geschieht, meiner Erfahrung nach extrem gering. Aber ich bin jetzt am Überlegen, ob ich das Context-Objekt nicht doch durchreiche, da mir die Singleton-Lösung nicht besonders gut gefällt. Was mich bis jetzt daran gestört hat, war, dass auch das View dann das Context-Objekt explizit übergeben bekommen muss - Auf der anderen Seite greift es stattdessen über ein Singleton darauf zu, was eigentlich noch schlimmer ist.

                Daher tendiere ich dazu, dass Context-Objekt doch manuell an Components (entsprechend Controllern) und Views durchzureichen.

                Kommentar


                • #9
                  Ich überlege gerade, ob man nicht ein Singleton-Request-Wrapper-Objekt realisieren sollte. Jeder "neue" Reguest innerhalb der HMVC-Knoten wird dann im RequestWrapper-Stack gespeichert. Der Request selbst beinhaltet dann auch den DI-Container, die Konfiguration etc...

                  Also
                  PHP-Code:
                  RequestWrapper::getInstance()->getMaster()->getConfig()->foo
                  RequestWrapper
                  ::getInstance()->getSub(2)->getContainer()->get('log'); // zweittiefste Node hervorholen 
                  Interessant wird es dann, wenn man die Subrequests nicht anhand einer Nummer (wie o.g.) aufruft, sondern wenn jeder Subrequest benannt ist, so dass jeder Subrequest anhand eines Namens identifiziert werden kann. Nur eine spontane Eingebung.
                  Was mich stört, ist, dass der Request dazu missbraucht wird, Container und Config mit sich rumzuschleppen.

                  Kommentar


                  • #10
                    Was mich an diesen Subrequests stört, ist, dass das so klingt, als würde der komplette Dispatch-Prozess noch mal angestoßen. Mein Verständnis von HMVC ist, dass die einzelnen Knoten innerhalb des selben Life-Cycles benutzt werden sollten, weil sonst ein enormer Overhead entsteht.

                    Kommentar


                    • #11
                      Zitat von xm22 Beitrag anzeigen
                      Was mich an diesen Subrequests stört, ist, dass das so klingt, als würde der komplette Dispatch-Prozess noch mal angestoßen.
                      Natürlich. Ein neuer interner Request verläuft (bei mir) auch immer wie ein regulärer, er passiert etwa den Router, den Eingangsfilter etc.

                      Mein Verständnis von HMVC ist, dass die einzelnen Knoten innerhalb des selben Life-Cycles benutzt werden sollten, weil sonst ein enormer Overhead entsteht.
                      Naja, aber diesen Life-Cycle kann man nur mit Singletons realisieren, wie du oben schon beschrieben hast. Und damit hast du einen enormen Nachteil, wenn es um das Zurückverfolgen eines Requests geht.

                      Kommentar


                      • #12
                        Zitat von dsentker Beitrag anzeigen
                        Ein neuer interner Request verläuft (bei mir) auch immer wie ein regulärer, er passiert etwa den Router, den Eingangsfilter etc.
                        Was rechtfertigt einen derartigen Sub-Request bzw. in welchen Fällen kommt das zum Einsatz?

                        Kommentar


                        • #13
                          Wenn ich spezielle Routen anlege, dann sollen die nicht nur für Anfragen "von außen" gelten, sondern möchte diese benannten Routen auch intern nutzen. Ansonsten würden sie keinen Sinn machen. Es ist ja auch möglich, dass ein Subrequest anhand eines URL-Parameters angestoßen wird.

                          Kommentar


                          • #14
                            Zitat von xm22 Beitrag anzeigen
                            Das klingt gut. Was enthält bei euch das Kontext-Objekt?
                            Primär wirkliche Aufrufinformationen. Also z.B. ob der Aufruf per normalem Postback, per AJAX oder als Sub-Request kam. Auf welcher Site (unser Framework unterstützt verschiedene Personalities / Mandanten) der Request reinkam und sowas eben.

                            Eigentlich sollte da auch noch mehr rein, aber wir haben uns dann doch für "Never change a running system" entschieden. Die Konfiguration ist bei uns historisch bedingt ein Singleton unter der Annahme, dass die sich für einen HMVC Ablauf nicht zwischendrin ändert.

                            Kommentar


                            • #15
                              @mquadrat: danke für die Info.

                              auch immer wie ein regulärer, er passiert etwa den Router, den Eingangsfilter etc.
                              Was machst Du, wenn Du die Response auf einen Request einmal mit Layout und bei interner Benutzung ohne ausgeben möchtest? Insgesamt sehe ich das aber echt als Overhead - bisher hatte ich nie den Fall, dass HMVC-Knoten in einem anderen Context als ein anderer aufgerufen werden sollte. Was machst Du in einem Subrequest, wenn der User per http weiter geleitet werden soll?

                              Kommentar

                              Lädt...
                              X