自动装配以减少服务列表

时间:2017-07-19 00:44:55

标签: symfony dependency-injection doctrine

在多租户系统中,我将当前用户角色注入我的所有Doctrine存储库,以确保用户只能看到他们有权访问的内容:

class SiteRepository extends SecurityAwareRepository
{
    public function createQueryBuilder($alias, $indexBy = null)
    {
        $qb = $this->_em->createQueryBuilder()
                        ->select($alias)
                        ->from($this->_entityName, $alias, $indexBy)
                        ->orderBy("$alias.name");

        switch ($this->getHighestRole()) {
            case 'ROLE_PARTNER':
                $qb
                    ->innerJoin("$alias.BilledTo", 'o')
                    ->innerJoin('o.Users', 'u')
                    ->where('u.id=:user_id')
                    ->setParameter('user_id', $this->getUserId())
                ;
                break;
            case 'ROLE_CUSTOMER':
                $qb
                    ->innerJoin("$alias.Organisation", 'o')
                    ->innerJoin('o.Users', 'u')
                    ->where('u.id=:user_id')
                    ->setParameter('user_id', $this->getUserId())
                ;
                break;
            case 'ROLE_SUPERADMIN':
                //full access
                break;
            default:
                $qb->where('1=0');

        }
        return $qb;
    }

我目前正在将这些存储库加载为如下服务:

services:
    invoice_repository:
        class: AppBundle\Repository\InvoiceRepository
        factory: ["@doctrine", getRepository]
        arguments:
            - "AppBundle:Invoice"
        calls:
          - method: setTokenStorage
            arguments:
              - "@security.token_storage"
    site_repository:
        class: AppBundle\Repository\SiteRepository
        factory: ["@doctrine", getRepository]
        arguments:
            - "AppBundle:Site"
        calls:
          - method: setTokenStorage
            arguments:
              - "@security.token_storage"

我可以通过自动布线消除这种重复吗?如果是的话怎么办?

1 个答案:

答案 0 :(得分:2)

直到最近

有一段时间,我使用了一个特性并连接了你的例子中的setter注入,这是相当重复的。

然后,我开始在3.3中使用改进的自动装配来帮助连接我的存储库,如下所示:

services:
    _defaults:
        autowire: true
        autoconfigure: true
        public: false

    ...... redacted stuff ......

    Entity\PageRepository:
        public: true
        factory: ['@doctrine.orm.default_entity_manager', getRepository]
        arguments: [Entity\Page]

PageRepository内,我使用下面的特征:

trait AppContextTrait
{
    protected $appContext;

    /**
     * @required
     */
    public function setAppContext(AppContext $appContext)
    {
        $this->appContext = $appContext;
    }

    public function getAppContext(): AppContext
    {
        return $this->appContext;
    }
}

@required注释告诉autowirer在实例化类时调用方法。

我现在实际上只有很少的DIC配置,所有内容都是完全自动装配的,但存储库除外。存储库中仍然有很多重复。 DIC配置。

但现在,

在我阅读Magnus Nordlander's blog post about autowiring repositories之后,我开始设置我的存储库,类似于下面的Magnus示例。它避免了封闭的实体管理器问题,并允许自动装配处理DIC配置。现在我的DIC配置文件非常纤薄! :)

class UserRepository
{
    private $managerRegistry;

    public function __construct(\Doctrine\Common\Persistence\ManagerRegistry $managerRegistry)
    {
        $this->managerRegistry = $managerRegistry;
    }

    public function find($id): ?User
    {
        return $this->getManager()->find(User::class, $id);
    }

    public function findOneUsingACustomQuery($parameter): ?User
    {
        return $this->getManager()->createQueryBuilder()
            ->from(User::class, 'u')
            ->where('u.something = :param')
            ->setParameter('param', $parameter)
            ->setMaxResults(1)
            ->getQuery()
            ->execute()
            ->getSingleResult();
    }

    protected function getManager(): \Doctrine\ORM\EntityManager
    {
        return $this->managerRegistry->getManagerForClass(User::class);
    }
}