2016-05-02 10 views
1

私はSymfony 2 WebAppプロジェクトに取り組んでいます。統合ショップのロジックはMyShopBundleに実装されています。 MyShopBundle申し出内Symfony 2:循環参照を解決する

PaymentServices:問題を解決するための解決策を、私は完全にこのメッセージの意味を理解していないが、今のところ私が見つけた

バンドルにTwig Extensionを追加した後、私は例外を取得しますすべての種類の支払い処理に関連するさまざまなサービス。他にも、支払いステータスを監視し、自動的に電子メール通知をユーザーに送信します。さらにそれはisPaymentComplete(int userId)を提供します。

Twigテンプレートからの電子メールのコンテンツをレンダリングするには、PaymentServicesにはTwig_Environmentへの参照が必要です。サービスそのコンストラクタからこの参照を取得します。一方

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; 
    } 
} 

小枝拡張isPaymentComplete(int userId)の小枝のバージョンを作成するためにPaymentServiceへの参照が必要になります。

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; 
    } 
} 

これはサービスですservice.yml

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 } 

例外の原因は明確です:

PaymentService - >小枝 - > ShopExtension - > PaymentService

質問です:この問題を解決する方法は?

私はSymfonyの循環参照を扱う他の質問を見つけました。しかしそれらはすべて、Doctrine,FOSUserBundleなどのような共通のバンドル/サービスを使用して、いくつかの特別なケースに関連していました。これらのスレッドで解説されているソリューションはここでは機能しません。

明白な解決策はPaymentServiceを2つの部分に分割することです:isPaymentComplete(int userId)を含むものとupdatePaymentStatusを提供するものです。しかし、これらの2つの方法は他の共通の方法を使用しているので、これは音のように簡単ではありません。PaymentServiceサービス1と2が使用するすべての一般的な方法を含めupdatePaymentStatus

  • Service3含むisPaymentComplete
  • サービス2を含む

    • サービス1:ちょうどレバーの循環参照を移動するために避けるために、より深い私は、3つの部分にPaymentServiceを分割する必要があります

    これは(ほとんどの場合)機能しますが、非常に、非常に醜いでしょう。これらの3つのサービスのすべてのメソッドは、同じ目的(Paymentsを処理する)を提供するため、同じサービスに含める必要があります。サービスをさまざまな部分に分割することは、コードの構造化とは関係なく、循環参照を分割するためのハックによってのみ行われます。

    Iはすでにセッターにコンストラクタからの参照を移動しようとした:

    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 } 
    

    結果は依然として同じです。

    So:この参照の問題を解決するにはクリーンの解決策はありますか?

  • +0

    支払を更新するように、あなたは、あなたの決済サービスを分割することができ支払いの完了状態を尋ねる情報が分離されます。 – xabbuh

    答えて

    1

    この質問は、依存性の少ないサービスを増やす必要があることを意味します。たとえば、TwitterのHTML電子メールを取得し、データでそれを水分補給するclientMailProviderのようなサービスを持つことができます。このサービスは、例えば、店舗決済サービスまたは他のサービスによって呼び出される。

    は、今すぐあなたの問題のために、私はあなたの代わりに、全サービスの小枝のテンプレート部分を注入することができると思う:

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

    サービス

    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)); 
         ... 
        } 
    
    関連する問題