在多租户系统中,我将当前用户角色注入我的所有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"
我可以通过自动布线消除这种重复吗?如果是的话怎么办?
答案 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);
}
}