自动装配,以减少服务
问题描述:
的名单在多租户系统,我注入当前用户角色为我所有的学说存储库,以确保用户只能看到他们有机会获得:自动装配,以减少服务
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"
我可以消除这种重复与自动装配,如果是如何?
答
直到最近
有一段时间,我用了一个特质和有线的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
虽然与autowire无关,但实际上可以插入自己的RepositoryFactory类,从而可以为您注入令牌存储。消除呼叫部分。 https://*.com/questions/44008937/how-can-i-inject-class-inside-custom-repository-symfony-2-7/44070750#44070750使用你自己的工厂在概念上好一点,因为它允许$ em-> getRepo按预期工作。 – Cerad
避免调用部分的另一种方法是使用父服务。 https://symfony.com/doc/current/service_container/parent_services.html – Cerad
Cerad,我实现了一个自定义仓库工厂,你可以添加这个作为我能接受的答案吗? – jdog