Ankündigung

Einklappen
Keine Ankündigung bisher.

Symfony services.yml parameterübergabe

Einklappen

Neue Werbung 2019

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

  • Symfony services.yml parameterübergabe

    Hey Zusammen,
    kann mir zufällig jemand verraten wie man vom Controller aus Parameter an einen Konstruktor einer Serviceklasse übergeben kann?

    folgendes Beispiel:


    TestController.php
    PHP-Code:
    class TestController {

    public function 
    startAction(TestService $testservice) {

    $a 1;
    $b 2;

    $testservice->setParameter($a$b);  //Ich weiß das das falsch ist, dass würde nur gehen, wenn setParameter eine Funktion in der Klasse wäre.
                                                                  
    Ich möchte aber das es über den Konstruktor gehtaber habe keine Ahnung wie/ob es so irgendwie funktioniert.
    }


    TestService
    PHP-Code:
    class TestService {

    private 
    $a;
    private 
    $b;
    private 
    $repository;

    public 
    __construct(TestRepository $testRepo$a$b) {
    $this->repository $testRepo;
    $this->$a;
    $this->$b;
    }

    Services.yml

    parameters:

    a : '';
    b : '';


    AppBundle\Services\TestService:
    class: 'AppBundle\Services\TestService
    arguments: ['%a%', '%b%']

    AppBundle\Repository\TestRepository:
    class: 'AppBundle\Repository\TestRepository
    factory: ['@doctrine.orm.entity_manager', getRepository]
    arguments: [AppBundle:Test]





    Wenn ich direkt in der services.yml den Parameter einen Wert zuweise, dann werden Sie auch an die TestService-Klasse übergeben, aber ich möchte das gerne über den Controller machen oder macht es keinen Sinn?

    Mein Gedanke ist, dass die TestService-Klasse ohne die Parameter und das Repository eh nicht funktioniert, also macht es eher Sinn die Parameterübergabe über den Konstruktor laufenzulassen anstatt über Setter-Funktionen.


    Danke für eure Hilfe!

    Yugox

  • #2
    Was genau sind es denn für Parameter in deinem Beispiel?

    Ich kenne so auf die Schnelle 3 Arten:

    1) Abhängigkeiten zu anderen Logikklassen / Services (geht problemlos über den Konstruktor)
    2) App-Konstanten, die in der parameters.yml hinterlegt sind wie bspw. irgendwelche Tokens zu API-Aufrufen (geht problemlos über den Konstruktor)
    3) Parameter, die aus dem Programmablauf kommen wie bspw. eine Entity oder irgendwelche "dynamischen" Werte (würde ich direkt in den Methodenaufruf geben oder zur Not über Setter-Injection lösen)

    Kommentar


    • #3
      Einmal wird, wie man in der TestService-Klasse sieht, ein Repository gebraucht. Da bin ich mir nun auch nicht sicher ob ich den über den Controller auch übergeben muss oder ob das so ausreicht, wenn ich das nur in der TestService-Klasse initialisiere (Zumindestens funktioniert das bis dato so).

      Ansonsten sind es dynamische Parameter die anhand eines Posts übergeben werden, also keine festen Werte wie Token.

      Kommentar


      • #4
        3) Parameter, die aus dem Programmablauf kommen wie bspw. eine Entity oder irgendwelche "dynamischen" Werte (würde ich direkt in den Methodenaufruf geben oder zur Not über Setter-Injection lösen)
        Wie würde das in meinem Fall aussehen ohne Setter-Injection?

        Kommentar


        • #5
          Hat sonst keiner Anregungen oder Lösungsvorschläge?

          Kommentar


          • #6
            Na einfach $this->get('service.id')->doSomething($a, $b); im Controller. Damit stünden die Parameter innerhalb der Methode zur Verfügung.

            Das wäre ein Beispiel für Setter-Injection über die services.yml:

            Code:
            listener.login:
                class: AppBundle\Logic\LoginListener
                parent: security.authentication.success_handler
                calls:
                    - { method: 'setUserManager', arguments: [ '@manager.user' ] }

            Kommentar


            • #7
              Na einfach $this->get('service.id')->doSomething($a, $b); im Controller. Damit stünden die Parameter innerhalb der Methode zur Verfügung.
              Das wäre ein Beispiel für Setter-Injection über die services.yml:
              Hey wario,
              danke für deinen Lösungsvorschlag. Ich habe mal gelesen, dass man "$this->get()" vermeiden sollte, deshalb läuft es bei mir ja so:

              PHP-Code:
              class TestController {

              public function 
              startAction(TestService $testservice) {

              $a 1;
              $b 2;

              $testservice->setParameter($a$b);  //Ich weiß das das falsch ist, dass würde nur gehen, wenn setParameter eine Funktion in der Klasse wäre.
                                                                            
              Ich möchte aber das es über den Konstruktor gehtaber habe keine Ahnung wie/ob es so irgendwie funktioniert.
              }

              Wie dabei erwähnt, wäre "setParameter" eine Methode, wie z.B. eine Setter-Funktion dann könnte ich das damit realisieren(was auch momentan der Fall ist). Allerdings suche ich nach der Möglichkeit eines Constuctor-Injection und kein Setter-Injection, falls ein dynamischer Constructor-Injection möglich wäre.

              Kommentar


              • #8
                Meines Wissens nach geht das nicht, das hat aber keinen Anspruch auf Richtigkeit .

                Laut Doku und wie von mir oben geschrieben kommen für die Konstuktor-Injection andere Elemente des Containers, sprich Services und Parameters, in Frage.

                Warum muss dein Service die Parameter denn unbedingt als Properties haben, statt sie einfach in den Methodenaufruf zu übergeben?

                Kommentar


                • #9
                  Repositories müssen auch in Symfony4 per Hand als Service deklariert werden. Dazu musst du einfach die Factory für das Repository verwenden.
                  Code:
                  services:
                      App\Entity\PostRepository:
                            class: Doctrine\ORM\EntityRepository
                            factory: ['@doctrine.orm.default_entity_manager', getRepository']
                            arguments:
                                  - App\Entity\Post
                  Jetzt kannst du das Repositroy einfach per Constructor oder Setter Injection verwenden.

                  Es gibt aber noch andere Möglichkeiten, du kannst z.B. einfach den EntityManager im Constructor injecten. Dies macht meistens sogar mehr Sinn, da du ja bestimmt nicht nur Daten Abfragen möchtest.

                  https://www.tomasvotruba.cz/blog/201...ce-in-symfony/

                  PS.: Container Parameter nachträglich hinzufügen ist nicht möglich, da wenn der Controller ausgeführt wird, der Container ja bereits gebaut ist. Parameter können aber über eine Container Extension hinzugefügt werden. Die Datei liegt in deinem Bundle unter DepencyInjectio.
                  https://symfony.com/doc/current/conf...rs_in_dic.html

                  Kommentar


                  • #10
                    Vielen Dank an alle für die Anregungen.

                    Container Parameter nachträglich hinzufügen ist nicht möglich, da wenn der Controller ausgeführt wird, der Container ja bereits gebaut ist. Parameter können aber über eine Container Extension hinzugefügt werden. Die Datei liegt in deinem Bundle unter DepencyInjectio.
                    Das ist eine direkte Aussage, die mir sehr hilft, danke dafür Zeichen32


                    PS: Sehe ich das richtig das Constructor-Injektion eher Sinn machen, wenn man keine dynamischen, sondern feste Parameterwerte hat?

                    Kommentar


                    • #11
                      Zitat von yugox Beitrag anzeigen
                      PS: Sehe ich das richtig das Constructor-Injektion eher Sinn machen, wenn man keine dynamischen, sondern feste Parameterwerte hat?
                      Ja, Constructor-Injection sollte immer verwendet werden für Abhängigkeiten ohne die die Klasse nicht lauffähig ist.
                      Für alle optionalen Abhängigkeiten bietet sich Setter-Injection an.


                      Kommentar


                      • #12
                        Zitat von wario Beitrag anzeigen
                        Was genau sind es denn für Parameter in deinem Beispiel?

                        Ich kenne so auf die Schnelle 3 Arten:

                        1) Abhängigkeiten zu anderen Logikklassen / Services (geht problemlos über den Konstruktor)
                        2) App-Konstanten, die in der parameters.yml hinterlegt sind wie bspw. irgendwelche Tokens zu API-Aufrufen (geht problemlos über den Konstruktor)
                        3) Parameter, die aus dem Programmablauf kommen wie bspw. eine Entity oder irgendwelche "dynamischen" Werte (würde ich direkt in den Methodenaufruf geben oder zur Not über Setter-Injection lösen)
                        und wieso keine Factory? Das Pattern ist wie dafür geschaffen.

                        [URL="https://github.com/chrisandchris"]GitHub.com - ChrisAndChris[/URL] - [URL="https://github.com/chrisandchris/symfony-rowmapper"]RowMapper und QueryBuilder für MySQL-Datenbanken[/URL]

                        Kommentar


                        • #13
                          Da hatte ich gar nicht dran gedacht. Wie würdest du es denn hier im konkreten Fall mit der Injection der Entity lösen?

                          Kommentar


                          • #14
                            So wie oben schon beschrieben habe löst man das mit einer Factory.

                            Code:
                             services:    
                                   App\Entity\PostRepository:          
                                   class: Doctrine\ORM\EntityRepository          
                                   factory: ['@doctrine.orm.default_entity_manager', getRepository']          
                                   arguments:                
                                         - App\Entity\Post
                            Du kannst natürlich für deinen Service auch eine eigene Factory schreiben, den Entity Manager injecten und dann deine Klasse erstellen und zurückgeben. Allerdings ist das viel zu viel Aufwand, wenn man es auch dem Container überlassen kann die Instanz zu erstellen.

                            http://symfony.com/doc/2.4/component...factories.html

                            Kommentar

                            Lädt...
                            X