2016-05-02 11 views
1

Ich arbeite an einem Symfony 2 WebApp-Projekt. Die Logik des integrierten Shops ist in MyShopBundle implementiert.Symfony 2: Resolve Rundschreiben

Nach einem Twig Extension auf das Bündel Hinzufügen erhalte ich eine Ausnahme:

ich völlig die Bedeutung dieser Nachricht verstehen, aber bisher habe ich keine Lösung, das Problem zu lösen:

Die PaymentServices innerhalb der MyShopBundle Angebote alle Arten von verschiedenen Dienstleistungen im Zusammenhang mit dem Zahlungsprozess. Neben anderen beobachtet es den Zahlungsstatus und sendet automatisch E-Mail-Benachrichtigungen an die Benutzer. Zusätzlich bietet es die isPaymentComplete(int userId) an.

Um den Inhalt einer E-Mail von einer Twig Vorlage darzustellen, benötigt die PaymentServices einen Verweis auf Twig_Environment. Die Leistungen erhält diese Referenz von seinem Konstruktor:

class MyPaymentService { 
    protected $twig; 

    public function __construct(\Twig_Environment $twig, ...) { 
     $this->twig = $twig; 
     ... 
    } 

    public function updatePaymentStatus(int userId) { 
     // Update Payment 
     ... 

     // Send notification to user 
     $mailBody = $this->twig->render('MyShopBundle:Emails:statusUpdate.html.twig', array('user_name' => $username)); 
     ... 
    } 

    public function isPaymentComplete(int userId) { 
     ... 
     return true; 
    } 
} 

Die Zweig Erweiterung auf der anderen Seite müssen einen Verweis auf die PaymentService einen Zweig Version von isPaymentComplete(int userId) zu erstellen:

class ShopExtension extends \Twig_Extension { 
    private $paymentService; 

    public function __construct(PaymentService $service, ...) { 
     $this->paymentService = $service; 
     ... 
    } 

    public function getName() { 
     return 'my_shop_bundle_extension'; 
    } 

    public function getFunctions() { 
     $functions = array(); 

     $functions[] = new \Twig_SimpleFunction('msb_IsPaymentComplete', array(
      $this, 
      'msb_IsPaymentComplete' 
     )); 

     return $functions; 
    } 

    public function msb_IsPaymentComplete($user) { 
     if ($this->paymentService) 
      return $this->paymentService->isPaymentComplete($user); 
     else 
      return false; 
    } 
} 

Dies ist der Dienst Definition in

services: 
    shop.payment.service: 
     class: MyShopBundle\Service\PaymentService 
     arguments: 
      - "@twig" 
      - ... 

    app_subscription.twig_extension: 
     class: MyShopBundle\Twig\ShopExtension 
     arguments: 
      - "@shop.payment.service" 
     tags: 
      - { name: twig.extension } 

Die Quelle der Ausnahme ist klar:

PaymentService -> Zweig -> ShopExtension -> PaymentService

Frage ist: Wie dieses Problem zu lösen?

Ich habe andere Fragen gefunden, die sich mit zirkulären Referenzen in Symfony beschäftigen. Aber sie waren alle mit einigen speziellen Fällen verwandt, die einige gemeinsame Pakete/Dienste wie Doctrine, FOSUserBundle, usw. verwendeten. Die in diesen Themen besprochenen Lösungen funktionieren hier nicht.

Die naheliegende Lösung wäre, die PaymentService in zwei Teile zu teilen: Eine, die isPaymentComplete(int userId) enthält und eine, die updatePaymentStatus bietet. Aber das ist nicht so einfach wie sein Sound, da diese beiden Methoden andere übliche PaymentService Methoden verwenden. Um zu vermeiden, nur den Kreis Bezug auf den Hebel bewegen tiefer ich müsste PaymentService in drei Teile aufgeteilt:

  • Dienste1 einschließlich isPaymentComplete
  • Service2 einschließlich updatePaymentStatus
  • Service3 einschließlich aller gängigen Methoden von Service1 und 2

Das würde (am wahrscheinlichsten) funktionieren, wäre aber sehr, sehr hässlich. Alle Methoden in diesen drei Diensten dienen demselben Zweck (behandeln Zahlungen) und sollten daher in denselben Diensten enthalten sein. Die Aufteilung der Dienste in verschiedene Teile hätte nichts mit Code-Strukturierung zu tun, sondern würde nur durch einen Hack den Zirkelbezug auflösen.

ich bereits versucht, den Verweis aus der Konstrukteurs zu einem Einrichter zu bewegen:

services: 
    shop.payment.service: 
     class: MyShopBundle\Service\PaymentService 
     calls: 
      - [ setTwig, [ "@twig" ] ] 

    app_subscription.twig_extension: 
     class: MyShopBundle\Twig\ShopExtension 
     calls: 
      - [ setService, [ "@shop.payment.service" ] ] 
     tags: 
      - { name: twig.extension } 

Das Ergebnis ist immer noch das gleiche.

Also: Gibt es eine saubere Lösung, um dieses Problem zu lösen?

+0

Sie Ihren Zahlungsservice aufgeteilt könnten, so dass die Aktualisierung Zahlung Informationen und Fragen nach dem Abschlussstatus einer Zahlung werden getrennt. – xabbuh

Antwort

1

Diese Frage bedeutet, dass Sie mehr Dienste mit weniger Abhängigkeiten benötigen. Zum Beispiel könnten Sie einen Dienst wie clientMailProvider haben, der die Zweig-HTML-E-Mail erhält und sie mit Ihren Daten hydratisiert. Dieser Dienst wird beispielsweise vom Zahlungsdienstanbieter oder in einem anderen Dienst aufgerufen.

Jetzt für dein Problem, ich glaube, Sie den Templat Teil Zweig anstelle des gesamten Service injizieren:

services: 
    shop.payment.service: 
     class: MyShopBundle\Service\PaymentService 
     arguments: 
      - "@templating" 

Der Service

use Symfony\Component\Templating\EngineInterface; 

class MyPaymentService { 
    protected $templating; 

    public function __construct(EngineInterface $templating, ...) { 
     $this->templating= $templating; 
     ... 
    } 

    public function updatePaymentStatus(int userId) { 
     // Update Payment 
     ... 

     // Send notification to user 
     $mailBody = $this->templating->render('MyShopBundle:Emails:statusUpdate.html.twig', array('user_name' => $username)); 
     ... 
    }