2016-11-05 4 views
2

DBに2つのテーブルがあります(questionanswer)。一つの質問には多くの答えがあります。Symfony2サービス

Answersがあります。question.typeに依存します。結果の配列を準備します。任意のフレームワークなしにアプリで

私はDBから特定のオブジェクト(SingleChoiceQuestionOpenQuestionMultipleChoiceQuestion)依存question.typeを返すFactoryクラスを有しています。すべてQuestionsは、abstractメソッドgetResultsと宣言された抽象クラスQuestionを継承しています。すべてのタイプには、結果を準備するための独自のビジネスロジックがあります。

このような状況では、工場でオブジェクトを作成したときに、メソッドgetResultsを使用していて、すべて正常に動作します。

私はそれをSymfonyで作成したいと思いますし、ドキュメントを読んでいます。私の意見では、すべての私のQuestionタイプのサービスを作成する必要があります。

結果配列を返すgenerateメソッドでAggregatedResultsManagerを作成しました。 question.typeに応じて、特定のserviceからgetResultsメソッドを呼び出します。

DB構造を変更することはできませんので、追加したいと思います。

私の質問:

  1. 私が作成し、services権利を使用していますか?私が間違っていたら、それを理解して正しい方法を教えてください。
  2. AggregatedResultsManagerのようないくつかのサービスと約18種類の質問タイプがあります。

各サービスでは、私はswitchを18個の選択肢で作成する必要があります。その防止方法は?

$services = [ 
    Question::SINGLE => 'app.single_choice_question', 
    Question::MULTIPLE => 'app.multiple_choice_question', 
    Question::OPEN => 'app.open_question', 
]; 

してから、そのような各サービスでそれを使用します:私はそれが最善の方法だと思う

$results = $this->container->get($services[$this->question->getType()])->getResults($answers); 

switch ($this->question->getType()) { 
    case Question::SINGLE: 
     $results = $this->container->get('app.single_choice_question')->getResults($answers); 
     break; 
    // other types 
} 

私は種類やサービス名を持つ配列を作成するためのいくつかのアイデアを持っています18の選択肢を持つスイッチを使用しない。しかし、私は配列でサービス名をハードコードする必要があります。

マイコード:

サービス。YML

app.question: 
    class: AppBundle\Questions\Question 
    abstract: true 
    arguments: ['@doctrine.orm.entity_manager'] 

app.single_choice_question: 
    class: AppBundle\Questions\SingleChoice 
    parent: app.question 

app.agreggated_results_manager: 
    class: AppBundle\Results\AggregatedResultsManager 
    arguments: ['@doctrine.orm.entity_manager', '@service_container'] 

抽象的な質問

abstract class Question 
{ 
    /** 
    * @var EntityManager 
    */ 
    protected $em; 

    public function __construct(EntityManager $em) 
    { 
     $this->em = $em; 
    } 

    abstract public function getResults($answers); 
} 

SingleChoice

class SingleChoice extends Question 
{ 
    public function getResults($answers) 
    { 
     $results = []; 

     // business logic 

     return $results; 
    } 
} 

結果

class AggregatedResultsManager 
{ 
    /** 
    * @var EntityManager 
    */ 
    private $em; 

    /** 
    * @var Question 
    */ 
    private $question; 

    /** 
    * @var ContainerInterface 
    */ 
    private $container; 

    public function __construct(EntityManager $em, ContainerInterface  $container) 
    { 
     $this->em = $em; 
     $this->container = $container; 
    } 

    public function generate() 
    { 
     if (!$this->question) { 
      throw new \LogicException('Question is not set'); 
     } 

     $answers = $this->em 
      ->getRepository('AppBundle:Answer') 
      ->findBy(['question' => $this->question]); 

     $results = []; 

     if (empty($answers)) { 
      return $results; 
     } 

     switch ($this->question->getType()) { 
      case Question::SINGLE: 
       $results = $this->container->get('app.single_choice_question')->getResults($answers); 
       break; 
      // other types 
     } 

     return $results; 
    } 


    public function setQuestion(Question $question) 
    { 
     $this->question = $question; 
    } 
} 

コントローラ

public function questionIdsAction(Question $question) 
{ 
    $resultsManager = $this->get('app.agreggated_results_manager'); 
    $resultsManager->setQuestion($question); 
    $results = $resultsManager->generate(); 

    return new JsonResponse($results); 
} 
+0

問題が何であるか把握しようとするのは苦労します。複数の場合もありますか?役に立つ答えが得られない場合は、少し単純化しようと考えるかもしれません。 – Cerad

+0

@セラードあなたは右です!私が彼が求めている唯一の本当の疑問は、「サービスを作成して使用しているのですか?」 –

+0

@Ceradフィードバックをいただきありがとうございました。私は質問を追加しました。 – wtk13

答えて

1

私はあなたが18個のQuestionTypesを持っていると言っているのですが、エンティティマネージャがその作業を行うために必要なAbstractQuestionを拡張していますか? 18のサービスを作ってからコンテナを使うのではなく、質問工場を作ることをお勧めします。

class QuestionFactory 
    public function __construct($entityManager) 
     $this->entityManager = $entityManager; 
    public function create($questionType) 
     switch($questionType) { 
      case Question::SINGLE: return new SingleQuestion($this->entityManager); 

その後、結果マネージャにファクトリを注入します。

この手法では、一連のサービスを作成してコンテナを渡す必要がなくなります。あなたはまだswitch文を持っていますが、それは大丈夫です。

問題が発生する可能性がある唯一の問題は、QuestionTypesに追加の依存関係が必要な場合です。この場合、サービスを使用することに戻ることがあります。

関連する問題