自动装配,以减少服务

问题描述:

的名单在多租户系统,我注入当前用户角色为我所有的学说存储库,以确保用户只能看到他们有机会获得:自动装配,以减少服务

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

虽然与autowire无关,但实际上可以插入自己的RepositoryFactory类,从而可以为您注入令牌存储。消除呼叫部分。 https://*.com/questions/44008937/how-can-i-inject-class-inside-custom-repository-symfony-2-7/44070750#44070750使用你自己的工厂在概念上好一点,因为它允许$ em-> getRepo按预期工作。 – Cerad

+1

避免调用部分的另一种方法是使用父服务。 https://symfony.com/doc/current/service_container/parent_services.html – Cerad

+0

Cerad,我实现了一个自定义仓库工厂,你可以添加这个作为我能接受的答案吗? – jdog

直到最近

有一段时间,我用了一个特质和有线的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后,我已经开始建立我的仓库类似于下面马格努斯的例子。它避免了封闭的实体管理器问题,并且它可以让自动装配处理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); 
    } 
} 
+0

这也是一个非常好的答案,我看过那篇文章。但是在这一点上还没有选择这个,因为我不清楚他在公关时碰到了什么问题。希望了解更多 – jdog