PHP MySQL PDO多表查询:如何按表名索引结果数组?
实现PDO多表查询结果按表名索引返回(类似CakePHP风格)
当然可以实现!我之前做项目的时候也碰到过这种重复字段名的麻烦,用PDO完全能复刻CakePHP那种按表名分组返回结果的效果,下面给你两种实用的方案,亲测有效:
方案一:手动字段别名 + 结果重组
这是最直接的方式,适合查询逻辑不复杂的场景:
步骤1:给重复字段加表名前缀
写SQL的时候,给每个重复字段指定带表名的别名,比如:
$sql = " SELECT u.id AS users_id, u.status AS users_status, u.user_id AS users_user_id, p.id AS posts_id, p.status AS posts_status, p.user_id AS posts_user_id FROM users u JOIN posts p ON u.id = p.user_id WHERE u.deleted = 0 "; $stmt = $pdo->prepare($sql); $stmt->execute(); $rawResults = $stmt->fetchAll(PDO::FETCH_ASSOC);
步骤2:遍历重组数组
把返回的原始结果,按表名拆分成嵌套数组:
$formattedResults = []; foreach ($rawResults as $row) { $formattedRow = [ 'users' => [], 'posts' => [] ]; foreach ($row as $key => $value) { // 拆分别名:比如users_id拆成表名users和字段id list($tableName, $fieldName) = explode('_', $key, 2); if (isset($formattedRow[$tableName])) { $formattedRow[$tableName][$fieldName] = $value; } } $formattedResults[] = $formattedRow; }
这样得到的$formattedResults就是类似CakePHP的结构:每个元素里以表名为键,对应表的字段数组为值。
方案二:自定义PDO获取模式(更优雅的复用方案)
如果经常需要这种格式的结果,可以封装一个自定义的获取方法,或者利用PDO的PDO::FETCH_FUNC来处理:
封装处理函数
function fetchByTableName($row) { $result = []; foreach ($row as $key => $value) { // 这里假设你的SQL里字段别名是`表名.字段名`,比如users.id if (strpos($key, '.') !== false) { list($tableName, $fieldName) = explode('.', $key, 2); $result[$tableName][$fieldName] = $value; } else { // 非重复字段直接放在根级或者指定默认表 $result['_default'][$key] = $value; } } return $result; }
使用自定义函数获取结果
写SQL的时候用表名.字段名作为别名:
$sql = " SELECT u.id AS `users.id`, u.status AS `users.status`, p.id AS `posts.id`, p.status AS `posts.status` FROM users u JOIN posts p ON u.id = p.user_id "; $stmt = $pdo->prepare($sql); $stmt->execute(); $formattedResults = $stmt->fetchAll(PDO::FETCH_FUNC, 'fetchByTableName');
这种方式的好处是可以把处理逻辑封装起来,每次查询只要按规则写别名,就能直接得到想要的结构。
注意事项
- 不管用哪种方法,SQL里的别名规则要统一,要么用
表名_字段名要么用表名.字段名,避免拆分出错 - 如果表名本身包含下划线或者点,要调整拆分逻辑(比如用其他分隔符,或者在SQL里给表名加特殊标记)
- 对于大数据量的查询,第二种方法的性能和第一种差不多,都是遍历一次结果,不用太担心性能问题
内容的提问来源于stack exchange,提问作者Med.ZAIRI
相关产品推荐
相关产品推荐

