You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony4使用findBy查询roles字段返回空结果该如何解决?

问题原因

你的roles字段是JSON类型,Doctrine默认的findBy方法对JSON字段执行的是完全匹配逻辑:

  • 如果你传字符串ROLE_CANDIDATE,会匹配数据库中roles字段值完全等于"ROLE_CANDIDATE"的记录,而你实际存储的是JSON数组格式["ROLE_CANDIDATE","ROLE_USER"],自然匹配不到
  • 如果你传数组['ROLE_CANDIDATE'],会匹配roles完全等于["ROLE_CANDIDATE"]的记录,你存储的数组多了ROLE_USER,同样匹配失败
解决方法

推荐在自定义的UserRepository中编写基于JSON包含的查询方法,步骤如下:

  1. 首先确保你的MySQL版本 >= 5.7(支持JSON函数),如果项目没有安装Doctrine JSON扩展,先执行安装:
    composer require beberlei/doctrineextensions
    然后在config/packages/doctrine.yaml中配置JSON_CONTAINS函数:
doctrine:
    orm:
        dql:
            string_functions:
                JSON_CONTAINS: DoctrineExtensions\Query\Mysql\JsonContains
  1. 在App\Repository\UserRepository中添加自定义查询方法:
public function findByRole(string $role): array
{
    return $this->createQueryBuilder('u')
        ->andWhere('JSON_CONTAINS(u.roles, :role) = 1')
        // JSON_CONTAINS要求参数为合法JSON格式,用json_encode自动给字符串加双引号
        ->setParameter('role', json_encode($role))
        ->getQuery()
        ->getResult();
}
  1. 修改控制器中的查询逻辑,调用自定义方法:
if ($request->query->get('role')) {
    $selectedRole = $request->query->get('role');
    $users = $this->getDoctrine()
        ->getRepository(User::class)
        ->findByRole($selectedRole);
} else {
    $users = $this->getDoctrine()
        ->getRepository(User::class)
        ->findAll();
}
可选方案(不安装扩展,用原生SQL)

如果你不想安装额外扩展,可以直接用原生SQL查询:

$conn = $this->getDoctrine()->getConnection();
$sql = 'SELECT * FROM user WHERE JSON_CONTAINS(roles, ?)';
$stmt = $conn->prepare($sql);
$stmt->execute([json_encode($selectedRole)]);
$users = $stmt->fetchAllAssociative();

如果你使用PostgreSQL数据库,JSON包含查询语法需要调整为u.roles::jsonb ? :role,参数不需要json_encode,直接传入角色字符串即可。

内容的提问来源于stack exchange,提问作者Ahmed Ferjani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 04:15:09