Php Symfony2服务

Php Symfony2服务,php,symfony,service,Php,Symfony,Service,我有两个DB表格(问题和答案)。一个问题有很多答案 我得到了一些答案并取决于问题。键入我准备结果数组 在没有任何框架的应用程序中,我有工厂类,该类返回特定对象(SingleChoiceQuestion,OpenQuestion,MultipleChoiceQuestion)依赖于数据库中的question.type。所有Questions扩展了抽象类Question,该类声明了abstract方法getResults。所有类型都有自己的业务逻辑来准备结果 所以在这种情况下,当我通过工厂创建对象时

我有两个DB表格(
问题
答案
)。一个问题有很多答案

我得到了一些
答案
并取决于
问题。键入
我准备结果数组

在没有任何框架的应用程序中,我有
工厂
类,该类返回特定对象(
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感谢大家的反馈。我补充了一些问题。