Doctrine技术问询:如何用PHP结合Doctrine编写指定JSON查询(含可选参数)
使用PHP结合Doctrine实现指定JSON条件查询
需求说明
要实现对应SQL的查询逻辑,其中7作为可选参数:desired,仅当参数存在时才添加JSON包含检查条件。
方式一:使用Doctrine QueryBuilder(ORM风格)
适合用实体类映射数据库表的场景,通过QueryBuilder构建安全的DQL查询:
use Doctrine\ORM\EntityManagerInterface; use App\Entity\Club; // 假设你的实体类是Club,对应club表 class ClubRepository { public function __construct(private EntityManagerInterface $entityManager) {} public function getClubs(int $clubId, ?string $desiredActivity = null) { // 初始化QueryBuilder $qb = $this->entityManager->createQueryBuilder(); $qb->select('c') ->from(Club::class, 'c') ->where('c.club = :clubId') ->setParameter('clubId', $clubId); // 处理可选参数:仅当desiredActivity不为空时添加JSON条件 if ($desiredActivity !== null) { // 调用MySQL原生JSON函数,通过Doctrine表达式构建条件 $jsonCondition = $qb->expr()->isTrue( $qb->expr()->func( 'JSON_CONTAINS', $qb->expr()->func('JSON_EXTRACT', 'c.data', '$.activities.*'), ':desired', '$' ) ); $qb->andWhere($jsonCondition) // 注意:如果数据库中activities是字符串数组,参数需要带双引号;数字数组则直接传数值 ->setParameter('desired', sprintf('"%s"', $desiredActivity)); } // 执行查询并返回结果 return $qb->getQuery()->getResult(); } }
调用示例
// 获取EntityManager实例(根据你的框架,比如Symfony可通过依赖注入获取) $clubRepo = $entityManager->getRepository(Club::class); // 1. 仅查询club=34558的记录 $clubs = $clubRepo->getClubs(34558); // 2. 同时检查activities包含"7"的记录 $clubsWithActivity7 = $clubRepo->getClubs(34558, '7');
方式二:使用原生SQL查询
如果不需要实体映射,直接执行原生SQL更直观:
use Doctrine\ORM\EntityManagerInterface; class ClubService { public function __construct(private EntityManagerInterface $entityManager) {} public function getClubs(int $clubId, ?string $desiredActivity = null) { $sql = 'SELECT * FROM club WHERE club = :clubId'; $params = ['clubId' => $clubId]; // 添加可选的JSON条件 if ($desiredActivity !== null) { $sql .= ' AND JSON_CONTAINS(JSON_EXTRACT(data, \'$.activities.*\'), :desired, \'$\') IS true'; $params['desired'] = sprintf('"%s"', $desiredActivity); } // 执行原生SQL $stmt = $this->entityManager->getConnection()->prepare($sql); $stmt->execute($params); // 返回关联数组格式的结果 return $stmt->fetchAllAssociative(); } }
注意事项
- 始终使用参数绑定(
:clubId、:desired)避免SQL注入风险,不要直接拼接参数到SQL字符串中。 - 根据数据库中
data->activities的实际类型调整参数格式:如果是数字数组,参数直接传数值(如7)即可;如果是字符串数组,需要包裹双引号(如"7")。
内容的提问来源于stack exchange,提问作者vukojevicf
相关产品推荐
相关产品推荐

