Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice Symfony2 (Factory) Service

Yesterday I had a discussion at the IRC Symfony2 channel about best practice approaches and tutorials (book, cookbook on sf2-website).

  1. Someone said services have always to be stateless. He meant that there should be no connection to an Entity in a service class. But how should I work with user generated content if I need the content from database preformatted?

  2. Although someone said the service should be stateless I created a service and a factory service based on this tutorial: http://brentertainment.com/2012/02/28/contextualizing-your-symfony2-application-with-the-service-container/

The naming of my configuration services is currently a bit bad, but I have no strategy or good naming concept in the moment.

Currently I call $this->get('test.conf')->getCategory('data-browser') in the Controller. It "feels good" to do this by that way, because I don't have to repeat the function in the controller. The service test.conf then calls the factory service test.conf_factory, which get an instance of service.configuration.

Questions:

  • Are services the right place to get preformatted content like I do here?

  • Is the service configuration correct? Or could I simplify test.conf_factory, test.conf and test.configuration in any way? Currently I really don't know if I'm doing it right.

  • Would it be better (or is it possible) to use the service test.configuration and create another service which just creates in the constructor an instance of test.configuration and returns by an call of the method 'get' the instance? (http://symfony.com/doc/current/components/dependency_injection/introduction.html) Is there a proved way like most of the symfony developers do that?

The configuration factory:

namespace Test\CoreBundle\Factory;

use Test\CoreBundle\Entity\Account;
use Test\CoreBundle\Service\Configuration;


class ConfigurationFactory
{
    private $user;
    private $configuration;

public function __construct(Account $user = null, Configuration $configuration)
    {
        $this->user = $user;
        dump($user);
        $this->configuration = $configuration;
    }

    public function get()
    {
        if ($this->user) {
         //   dump($this->user);
            $this->configuration->setAccountid($this->user->getId());
        }
        return $this->configuration;
    }
}

The configuration serivce:

<?php
namespace test\CoreBundle\Service;

class Configuration {

    private $em;

    private $category;

    private $accountid;

    /**
     * Values from database
     * @var array
     */
    private $ValuesFromDB = null;

    public function __construct($em)
    {
        $this->em = $em->getRepository('TestCoreBundle:Conf');
    }

    public function setAccountid($accountid) {
        $this->accountid = $accountid;
        $this->loadAll();
    }
    public function loadAll() {
         $DBconf = $this->em->findAllByAccount($this->accountid);

         foreach($DBconf as $key => $conf) {
             $values[$conf->getCategory()][$conf->getKey()] = $conf->getValue();
        }

         $this->ValuesFromDB = $values;

    }

    public function setCategory($category) {
        $this->category = $category;
    }

    public function getCategory($category) {
        return $this->ValuesFromDB[$category];
    }

    public function get($key) {
        return $this->ValuesFromDB[$this->category][$key];
    }

}
services:
    test.account_factory:
        class: test\CoreBundle\Factory\AccountFactory
        arguments: [@security.context]
    test.account:
        class: test\CoreBundle\Entity\Account
        factory_service: test.account_factory
        factory_method: get


    test.configuration:
        class: test\CoreBundle\Service\Configuration
        arguments: [@doctrine.orm.entity_manager]          

    test.conf_factory:
        class: test\CoreBundle\Factory\ConfigurationFactory
        arguments: 
            - @test.account
            - @test.configuration

    test.conf:
        class: Configuration
        factory_service: test.conf_factory
        factory_method: get
like image 973
mipapo Avatar asked Nov 09 '22 13:11

mipapo


1 Answers

I'm not sure if I understand your design issues very well, but I guess that what you are actually trying to do is to retrieve some data from your database according to a specific entity (here, your user). I'll try then to share you my opinion :

What I can see from your design is that you misunderstood the Factory concept : here, it is clearly useless.

  • First, what you tried to design here is NOT a factory. It seems to be more like you tried to use the dependency injection principle without really mastering it.
  • Second, I think that when you have to implement such designs and implementing such tools, you have to think of what you are actually really trying to do, and what your tool should do. From what I can understand from your problem, you seem to want to retrieve some specific data related to your users that are not linked to your entity. The first question that I would ask is : why is your data not linked to the users, in your business-logic ?

Then, I would try to rething your tool by thinking : what should my tool do ? Don't you think that the design that you're implementing is too complex ?

If I understand what you want to do well, I guess that you could use your tool by :

  • First, retrieving manually your Account. No need to inject any Account or to create an instance of Configuration for each Account. I guess that for your higher level code, you can first retrieve your account.
  • Second, use a service (yes, a service, because a service is no more but a simple class with extra cool stuff with DI, etc) that retrieves the data you need.

Your questions in the beginning of your post are actually not meant to be asked, because you should not inject an instance of Account in your class. In the end, something like :

// I get my account 
$myAccount = $this->getEntityManager()->getRepository('TestCoreBundle:Conf')->find(/* ... */);
$configurationManager = $this->get('configuration_manager');
// The manager permits me to get the "extra stuff" related to this account.
$confStuff = $configurationManager->getConfigurationStuffFromAccount($myAccount);

... Should be the way you could fix your issues, if I understood it well.

That way :

  • You have a service configuration_manager that is NOT dependent to any repository or any account.
  • You use services and DI efficiently.
like image 173
MeuhMeuh Avatar answered Nov 15 '22 07:11

MeuhMeuh