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
services
right? 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