symfony2数据库查询面试核心是理解doctrine querybuilder设计意图与安全边界,重点考察参数绑定防注入、动态条件组织、n+1优化及多对多“且”条件实现。

Symfony2 中数据库查询面试,核心不是考你会不会写 SQL,而是看你是否真正理解 Doctrine QueryBuilder 的设计意图和安全边界。大厂常问的题,基本都围绕“怎么写才对”“为什么不能那么写”“线上出问题怎么定位”这三层展开。
QueryBuilder 参数绑定为什么必须用 setParameter()
这是防 SQL 注入的第一道硬性门槛。面试官如果问这个,实际在确认你有没有生产环境意识。
- 所有外部输入(GET/POST/命令行参数、用户 ID、搜索关键词)都必须走 setParameter(':key', $value),绝不能拼接字符串,比如
"WHERE name = '" . $_GET['name'] . "'" - 参数名要唯一,重复绑定同一名字会覆盖前值,导致条件丢失
- 从 Repository 调用 createQueryBuilder('a') 获取构建器,别名建议用单字母(如 u、p、o),避免长别名干扰可读性
动态条件怎么加才不翻车
后台列表页、高级搜索、导出筛选——这些场景下条件是可选的。面试官想看你怎么组织逻辑,而不是堆 if。
- 每个条件独立判断:先 if ($search) { $qb->andWhere('p.name LIKE :search')->setParameter(':search', "%$search%"); }
- 模糊匹配用 $qb->expr()->like('p.name', ':search'),手动加 % 号
- 范围查询优先用 $qb->expr()->between('p.price', ':min', ':max'),语义清晰、不易出错
关联表查多了变慢?N+1 是怎么发生的
查 100 个订单,再循环查每个订单的用户昵称——这就是典型 N+1。面试官可能给你一段低效代码让你改。
- 正确做法:用 leftJoin('o.user', 'u') 建立连接,再 addSelect('u.nickname') 显式声明要带出的字段
- 注意:只 leftJoin 不 addSelect,关联字段不会出现在结果里
- 如果只取部分字段,最后调用 getScalarResult(),跳过实体对象构造,减少内存开销
多对多“且”条件怎么写(比如红色+大号)
这是高频陷阱题。很多候选人直接写 WHERE a.slug = 'red' AND a.slug = 'large',显然永远不成立。
- 必须为每个属性条件单独 join:join('p.attributes', 'a0') 和 join('p.attributes', 'a1')
- 分别绑定参数:setParameter(':slug0', 'red') 和 setParameter(':slug1', 'large')
- 各自加条件:andWhere('a0.slug = :slug0') 和 andWhere('a1.slug = :slug1')
不复杂但容易忽略。真正拉开差距的,不是你会多少种写法,而是每一种你都清楚它背后的执行逻辑和边界条件。











