私はDBに2つのテーブルを持っている(question
とanswer
)。1つの質問には多くの答えがあります。
私はいくつかを取得し、結果の配列を準備することにAnswers
依存しquestion.type
ます。
フレームワークのないアプリでは、Factory
特定のオブジェクト(、、)を返すクラスがDBに依存しています。すべては抽象クラス拡張を宣言した方法を。すべてのタイプには、結果を準備するための独自のビジネスロジックがあります。SingleChoiceQuestion
OpenQuestion
MultipleChoiceQuestion
question.type
Questions
Question
abstract
getResults
したがって、この状況では、ファクトリでオブジェクトを作成したときにメソッドgetResults
を使用しており、すべてが正常に機能しています。
私はsymfonyでそれを作成したいと私は、ドキュメントを読んでください。私の意見では、私はすべての私のためのサービスを作成する必要がありQuestion
タイプを。
結果の配列を返すAggregatedResultsManager
メソッドgenerate
で作成しました。特定のからメソッドをquestion.type
呼び出すことに依存します。getResults
service
DB構造を変更できないことを付け加えたいと思います。
私の質問:
services
よね?間違った場合は、理解を助け、正しい方法を教えてください。AggregatedResultsManager
約18の質問タイプのようないくつかのサービスを持っています。各サービスswitch
で18の選択肢を作成する必要がありますが、それを防ぐにはどうすればよいですか?
switch ($this->question->getType()) {
case Question::SINGLE:
$results = $this->container->get('app.single_choice_question')->getResults($answers);
break;
// other types
}
タイプとサービス名を使用して配列を作成するアイデアがあります。
$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);
18の選択肢があるスイッチを使わないのが最善の方法だと思います。ただし、サービス名を配列にハードコーディングする必要があります。
私のコード:
services.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);
}
18のQuestionTypeがすべて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に追加の依存関係が必要な場合です。その場合、サービスの使用に戻る可能性があります。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加