我使用EasyadminBundle作为Symfony应用程序的后端。
我想通过他们的$roles
筛选我的用户,其中一个表只包含ROLE_WEBMASTER
,另一个表包含ROLE_ADMIN
,最后一个表则包含较宽松的表(ROLE_USER
(。
不幸的是,User
类的$roles
成员是一个数组。
class User implements UserInterface
{
/**
* @ORMColumn(type="json")
*/
private $roles = [];
}
我的存储后端是SQLite。
我尝试了两种解决方案:
1.使用搜索查询
- { icon: user-tie, label: admin, entity: User, params: {action: search, query: ROLE_ADMIN}}
什么都不做
2.使用DQL筛选器
webmaster:
class: AppEntityUser
label: Webmaster
list:
dql_filter: "'ROLE_WEBMASTER' IN entity.sqlRoles()"
带有
public function sqlRoles():string
{
return implode(', ',$this->getRoles());
}
但它启动了以下错误
在呈现模板的过程中引发异常("[语法错误]第0行,第65列:错误:应为=,<,<=,&llt;>,>=,!=,得到'IN'"(。
有办法表演这种把戏吗?还是我需要忘记这个想法?
为了过滤EasyadminBundle中的JSON数组,您不需要使用dql_filter
,因为filters
已经在该捆绑包中构建。
首先,你需要在你的实体描述中做一些准备:
easy_admin:
entities:
User:
class: AppEntityUser
list:
filters:
- { property: roles, type: array }
由于过滤器现在已经在实体上设置好了,我们可以在菜单中找到它:
easy_admin:
design:
menu:
- { icon: user-cog, label: webmaser, entity: User, params: { action: list, filters: { roles: { comparison: like, value: [ROLE_WEBMASTER] } } } }
我不知道easyAdmin,但DQL不会计算。
dql_filter: "'ROLE_WEBMASTER' IN entity.sqlRoles()"
您需要记住,在DQL上写的任何东西最终都必须被翻译成普通的旧SQL。这意味着使用实体方法是行不通的。
想想看:这些方法在对象实例化之前不能使用,在检索之后才能实例化,并且只有当SQL语句运行时才会进行检索,因此此时无法执行WHERE
筛选。
问题是,使用普通的Doctrine,您将无法通过JSON属性的属性内容进行过滤,基本上使用JSON_CONTAINS,Doctrine不支持它。
然而,并不是所有的希望都破灭了。有一些扩展可以为不同的后端添加对这些功能的支持,比如这个。
如果您安装并启用它,您可以将DQL过滤器更改为:
dql_filter: "JSON_CONTAINS(entity.roles, '"ROLE_WEBMASTER"', '$')"
只要你稍微努力一下,把所有的东西都绑在一起,这应该会奏效。
遗憾的是,由于您使用的是SQLite,您将无法使用以上内容。SQLite非常适合开发和嵌入式使用,但它的功能不如成熟的RDBMS丰富。
这是我使用dql_filter
时使用的解决方案,希望它能有所帮助:
easy_admin:
entities:
Player:
class: AppEntityUser
list:
dql_filter: "entity.roles LIKE '%%ROLE_PLAYER%%'"
Admin:
class: AppEntityUser
list:
dql_filter: "entity.roles LIKE '%%ROLE_ADMIN%%'"
easy_admin:
design:
menu:
- { label: 'Users' }
- { entity: 'Player', label: 'Players', icon: 'users' }
- { entity: 'Admin', label: 'Admins', icon: 'users' }