Php Symfony2服务
我有两个DB表格(Php Symfony2服务,php,symfony,service,Php,Symfony,Service,我有两个DB表格(问题和答案)。一个问题有很多答案 我得到了一些答案并取决于问题。键入我准备结果数组 在没有任何框架的应用程序中,我有工厂类,该类返回特定对象(SingleChoiceQuestion,OpenQuestion,MultipleChoiceQuestion)依赖于数据库中的question.type。所有Questions扩展了抽象类Question,该类声明了abstract方法getResults。所有类型都有自己的业务逻辑来准备结果 所以在这种情况下,当我通过工厂创建对象时
问题
和答案
)。一个问题有很多答案
我得到了一些答案
并取决于问题。键入
我准备结果数组
在没有任何框架的应用程序中,我有工厂
类,该类返回特定对象(SingleChoiceQuestion
,OpenQuestion
,MultipleChoiceQuestion
)依赖于数据库中的question.type
。所有Questions
扩展了抽象类Question
,该类声明了abstract
方法getResults
。所有类型都有自己的业务逻辑来准备结果
所以在这种情况下,当我通过工厂创建对象时,我使用方法getResults
,一切都很好
我想在Symfony中创建它,并阅读文档。在我看来,我应该为我所有的问题
类型创建服务
我已经使用返回结果数组的方法generate
创建了AggregatedResultsManager
。取决于问题。键入它从特定服务调用getResults
方法
我想补充一点,我不能改变数据库结构
我的问题:
我是否正在创建和使用服务
对吗?如果我做错了,请帮助我理解它,并告诉我正确的方法
我将提供多种服务,如AggregatedResultsManager
和大约18种问题类型
在每个服务中,我需要创建带有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个选择开关。但我需要在数组中硬编码服务名称
我的代码:
服务.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);
}
单选
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个问题类型,它们都扩展了一个抽象问题,需要实体经理来完成它的工作?与其提供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语句,但这没关系
唯一可能出现的问题是某些问题类型是否需要其他依赖项。在这种情况下,您可能会重新使用服务。很难找到问题所在。可能不止一个?如果你没有得到任何有用的答案,你可以试着把事情简化一下。“Cerad,你说得对!我看到他问的唯一真正的问题是:我创建和使用服务对吗?
@Cerad感谢大家的反馈。我补充了一些问题。