Symfony ACL 允许我授予对实体的访问权限,然后检查它:
if (false === $securityContext->isGranted('EDIT', $comment)) {
throw new AccessDeniedException();
}
但是,如果我在数据库中有数千个实体并且用户只能访问其中的 10 个,我不想将所有实体加载到内存中并对其进行水合。
如何在仅过滤用户有权访问的实体(在 SQL 级别)时执行简单的“SELECT * FROM X”?
Symfony ACL 允许我授予对实体的访问权限,然后检查它:
if (false === $securityContext->isGranted('EDIT', $comment)) {
throw new AccessDeniedException();
}
但是,如果我在数据库中有数千个实体并且用户只能访问其中的 10 个,我不想将所有实体加载到内存中并对其进行水合。
如何在仅过滤用户有权访问的实体(在 SQL 级别)时执行简单的“SELECT * FROM X”?
那么它就是:这是不可能的。
去年,我一直在研究一种替代 ACL 系统,该系统允许直接在数据库查询中进行过滤。
我公司最近同意开源,所以这里是: http: //myclabs.github.io/ACL/
正如@gregor 在之前的讨论中指出的那样,
在您的第一个查询中,获取用户有权访问的所有 object_identity_ids(针对特定实体/类 X)的列表(带有自定义查询)。
然后,在查询实体/类 X 的对象列表时,将“IN (object_identity_ids)”添加到您的查询中。
Matthieu,我对回答更多的猜想并不满意(因为我的猜想并没有给谈话增加任何有价值的东西)。所以我对这种方法做了一些基准测试(Digital Ocean 5$/mo VPS)。
正如预期的那样,使用 IN 数组方法时,表大小并不重要。但是大数组确实会让事情失控。
那么,Join approach
与IN array approach
?
当数组大小很大时,JOIN 确实更好。但是,这是假设我们不应该考虑表格大小。事实证明,实际上 IN 数组更快- 除非有一个大的对象表并且 acl 条目几乎涵盖了每个对象(请参阅链接的问题)。
我在一个单独的问题上扩展了我的推理。请参阅使用 Symfony 的 ACL 时,使用 JOIN 查询还是 IN 数组查询更好?
你可以看看Doctrine filters。这样您就可以扩展所有查询。我还没有这样做,并且记录了一些限制。但也许它对你有帮助。您将在此处找到 ACL 数据库表的描述。
更新
每个过滤器都将返回一个字符串,所有这些字符串都将添加到 SQL 查询中,如下所示:
SELECT ... FROM ... WHERE ... AND (<result of filter 1> AND <result of filter 2> ...)
表别名也被传递给过滤器方法。所以我认为你可以在这里添加子查询来过滤你的实体。