【问题标题】:Symfony2 - Create a Doctrine filter to select current user dataSymfony2 - 创建一个 Doctrine 过滤器来选择当前用户数据
【发布时间】:2014-07-08 00:01:03
【问题描述】:

我正在使用 Symfony 2 构建一个 Saas / 多租户应用程序。我创建了一个 Doctrine 事件订阅者来添加和更新行的所有者、创建它的用户、修改它的用户、时间戳等等.

现在我需要实现某种过滤器,这样当用户登录时,他只能看到来自他公司的数据。我的第一个虽然是使用 Doctrine preLoad 事件,但这个事件不存在......据我所知,我必须使用 Doctrine 过滤器,不是吗?如果是这样,此过滤器如何访问用户数据以读取公司 ID?我必须使用依赖注入来注入它吗?有什么标准方法可以实现我的目标吗?

更新 我正在寻找的是创建某种 Doctrine 插件/挂钩,所以每次我调用从数据库中获取数据的任何函数(find、findOneBy 等),并且我正在获取的实体实现了一个特定的接口,一个额外的'AND company_id=:id' SQL 序列被添加到生成的查询中,因此控制器或模型都不会接收来自其他公司的数据。

【问题讨论】:

标签: php symfony doctrine-orm multi-tenant saas


【解决方案1】:

为此,您可以使用 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();
}

【讨论】:

    【解决方案2】:

    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您还需要指出过滤函数应该使用局部变量 user,因为它有自己的范围,否则它不会。

    【讨论】:

    • 我不确定我们是否在谈论同一个...我需要一个过滤器,在将 SQL 命令发送到服务器之前更改它(添加一个简单的 'AND company_id=:id' ),并将此过滤器与 symfony 链接,因此在每次请求时,过滤器都会使用当前登录的用户 company_id...
    • 哦,我明白了。事实上,我们在谈论不同的事情!我正在回答如何在收到所有行后进行过滤。
    • @iamadev:这正是我想要避免的,接收所有行然后过滤它们。我希望它们在数据库引擎中被过滤,而不是在 PHP 中。
    猜你喜欢
    • 2022-01-23
    • 1970-01-01
    • 2021-09-20
    • 2013-08-22
    • 1970-01-01
    • 1970-01-01
    • 2019-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多