2016-11-05 2 views
2

DB에 2 개의 테이블이 있습니다 (questionanswer). 하나의 질문은 많은 해답을 가지고 있습니다.Symfony2 서비스

일부는 Answers이되고 question.type에 따라 결과 배열을 준비합니다. 어떤 프레임 워크없이 응용 프로그램에서

나는 DB에서 특정 객체 ( SingleChoiceQuestion, OpenQuestion, MultipleChoiceQuestion) 따라 question.type를 반환 Factory 클래스가 있습니다. 모두 Questionsabstract 메서드 getResults을 선언 한 추상 클래스 Question을 확장합니다. 모든 유형에는 결과를 준비하기위한 자체 비즈니스 로직이 있습니다.

따라서이 방법을 사용하면 공장에서 객체를 만들 때 getResults 메서드를 사용하면 모든 것이 잘 작동합니다.

Symfony에서 만들고 싶습니다. 설명서를 읽습니다. 제 생각에는 모든 Question 유형의 서비스를 만들어야합니다.

결과 배열을 반환하는 generate 메서드로 AggregatedResultsManager을 생성했습니다. question.type에 따라 특정 service에서 getResults 메서드가 호출됩니다.

나는 DB 구조를 변경할 수 없다고 덧붙이고 싶습니다.

내 질문 :

  1. 오전 내가 만들고 services를 잘 사용하고 계십니까? 내가 잘못했다면 이해하고 올바르게 가르쳐주세요.
  2. 나는 AggregatedResultsManager과 같은 18 가지 질문 유형과 같은 여러 서비스를 갖게됩니다.

각 서비스마다 18 가지 선택 사항이있는 switch을 작성해야합니다.이를 방지하려면 어떻게해야합니까?

$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

@Cerad 맞아! 그가 묻는 유일한 질문은 '서비스를 만들고 사용하고 있습니까?'입니다. –

+0

@Cerad 피드백을 보내 주셔서 감사합니다. 나는 질문을 추가했다. – wtk13

답변

1

당신은 18 개의 QuestionTypes가 모두 Entity Manager를 필요로하는 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 문을 가지고 있지만 괜찮습니다.

발생할 수있는 유일한 문제는 일부 QuestionType에 추가 종속성이 필요한 경우입니다. 어떤 경우에는 서비스를 다시 사용할 수 있습니다.

관련 문제