php - Symfony2 service -
i have 2 tables in db (question , answer). 1 question has many answers.
i answers , depends on question.type prepare results array.
in app without framework have factory class return specific object (singlechoicequestion, openquestion, multiplechoicequestion) depends question.type db. questions extends abstract class question has declared abstract method getresults. types have own business logic prepare results.
so in situation when have created object factory i'm using method getresults , works well.
i create in symfony , read documentation. in opinion should create services question types.
i have created aggregatedresultsmanager method generate returns results array. depends on question.type calls getresults method specific service.
i add, can't change db structure.
my questions:
- am creating , using
servicesright? if wrong, please me understanding , show me right way. - i have several services
aggregatedresultsmanager, 18 question types.
in each service need create switch 18 choices, how prevent that?
switch ($this->question->gettype()) { case question::single: $results = $this->container->get('app.single_choice_question')->getresults($answers); break; // other types } i have idea create array types , service names:
$services = [ question::single => 'app.single_choice_question', question::multiple => 'app.multiple_choice_question', question::open => 'app.open_question', ]; and use in each service that:
$results = $this->container->get($services[$this->question->gettype()])->getresults($answers); i think it's best way not use switch 18 choices. need hardcode service names in array.
my code:
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 question
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; } } 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 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; } } controller
public function questionidsaction(question $question) { $resultsmanager = $this->get('app.agreggated_results_manager'); $resultsmanager->setquestion($question); $results = $resultsmanager->generate(); return new jsonresponse($results); }
i think saying have 18 questiontypes extending abstractquestion needs entity manager it's work? instead of making 18 services , using container suggest making question factory:
class questionfactory public function __construct($entitymanager) $this->entitymanager = $entitymanager; public function create($questiontype) switch($questiontype) { case question::single: return new singlequestion($this->entitymanager); you inject factory results manager.
this approach avoids need create bunch of services , of needing pass around container. still have switch statement okay.
the problems might arise if questiontypes need additional dependencies. in case might using services.
Comments
Post a Comment