我正在使用Symfony 2构建Saas / Multitenant应用程序。我创建了一个Doctrine事件订阅者来添加和更新行的所有者,创建它的用户,修改它的用户,时间戳等等
现在我需要实现某种过滤器,因此当用户登录时,他只能看到他公司的数据。我的第一个是使用Doctrine preLoad事件,但是这个事件不存在......据我所知,我必须使用Doctrine过滤器,不是吗?如果是这样,该过滤器如何访问用户数据以读取公司ID?我必须使用依赖注入注入吗?有没有标准的方法来实现我的目标?
更新 我正在寻找的是创建某种Doctrine插件/钩子,所以每次我调用从数据库中获取数据的任何函数(find,findOneBy等),我正在获取的实体实现一个特定的接口,一个额外的'AND company_id =:id'SQL序列被添加到生成的查询中,因此控制器或模型都不会从其他公司接收数据。
答案 0 :(得分:5)
为此,您可以使用DoctrineFilter 来自官方文档Doctrine2 SQL Filters
的链接namespace Rwmt\Bundle\RwmtBundle\DoctrineFilters;
use Doctrine\ORM\Mapping\ClassMetaData,
Doctrine\ORM\Query\Filter\SQLFilter;
class MultiTenantFilter extends SQLFilter
{
public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
{
// Check if the entity implements the MultiTenant interface
if (!$targetEntity->reflClass->implementsInterface('Rwmt\Bundle\RwmtBundle\Entity\MultiTenant')) {
return "";
}
return $targetTableAlias.'.tenant_id = ' . $this->getParameter('tenantId');
}
}
要设置过滤器中使用的参数tenantId,您必须启用过滤器并设置参数
$filter = $em->getFilters()->enable('multi_tenant');
$filter->setParameter('tenantId', $tenant->getId(), 'integer');
MultiTenant界面只是实体实现的东西
namespace Rwmt\Bundle\RwmtBundle\Entity;
use Rwmt\Bundle\RwmtBundle\Entity\Tenant;
interface MultiTenant
{
public function setTenant(Tenant $tenant);
public function getTenant();
}
答案 1 :(得分:0)
在Doctrine2中过滤很简单。只需为变量分配一个过滤函数,然后通过ArrayCollection类中包含的filter()方法将该变量作为参数发送。
$closure = function($list_item) use($user) {
return $list_item->belongsToSameCompanyThatEmploys($user) === true;
};
$filtered_array_collection = $arrayYouWantToFilter->filter($closure);
在此示例中,您必须先在list_item的类中定义一个方法belongsToSameCompanyThatEmploys($user)
,如果它属于用户所在的同一公司,则返回true
。
UPDATE
您还需要指明过滤器函数应该使用局部变量用户,因为它不会因为拥有自己的范围而被使用。