PDO查询大量数据避内存耗尽:视图用fetch()不混逻辑的方案
解决方案
方案1:将PDO结果集包装为迭代器传入视图
PDO的Statement对象本身实现了可遍历接口,直接返回该对象给视图,视图通过foreach遍历即可自动触发逐行fetch(),既避免一次性加载所有数据占满内存,又严格遵循MVC分离规则——模型负责查询逻辑,视图仅做渲染。
模型层(functions.php)
function get_table_rows() { $pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass'); $stmt = $pdo->query('SELECT * FROM large_table'); // 返回Statement对象而非fetchAll()的数组 return $stmt; }
控制器层(示例:index.php)
// 调用模型获取结果集 $stmt = get_table_rows(); // 将结果集传入视图 include 'html.php';
视图层(html.php)
<table> <thead> <tr><th>ID</th><th>名称</th></tr> </thead> <tbody> <!-- 直接遍历Statement对象,底层自动逐行获取数据 --> <?php foreach ($stmt as $row): ?> <tr> <td><?= $row['id'] ?></td> <td><?= $row['name'] ?></td> </tr> <?php endforeach; ?> </tbody> </table>
方案2:控制器循环fetch,视图负责单一行渲染
把逐行获取的逻辑放在控制器,视图仅负责渲染单一行的HTML片段,彻底隔离查询逻辑与视图层。
模型层(functions.php)
function get_table_stmt() { $pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass'); return $pdo->query('SELECT * FROM large_table'); }
控制器层(示例:index.php)
$stmt = get_table_stmt(); // 加载表格头部视图 include 'table_header.php'; // 控制器内逐行获取数据,调用行视图渲染 while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { include 'table_row.php'; } // 加载表格尾部视图 include 'table_footer.php';
视图片段:table_header.php
<table> <thead> <tr><th>ID</th><th>名称</th></tr> </thead> <tbody>
视图片段:table_row.php
<tr> <td><?= $row['id'] ?></td> <td><?= $row['name'] ?></td> </tr>
视图片段:table_footer.php
</tbody> </table>
方案3:用生成器封装逐行获取逻辑
通过PHP生成器在模型层封装逐行fetch()的细节,返回生成器对象给视图,视图遍历生成器即可逐行获取数据,内存仅保留当前行数据,同时视图无需感知底层实现。
模型层(functions.php)
function get_table_rows_generator() { $pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass'); $stmt = $pdo->query('SELECT * FROM large_table'); while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { yield $row; } }
控制器层(示例:index.php)
$rows_generator = get_table_rows_generator(); include 'html.php';
视图层(html.php)
<table> <thead> <tr><th>ID</th><th>名称</th></tr> </thead> <tbody> <?php foreach ($rows_generator as $row): ?> <tr> <td><?= $row['id'] ?></td> <td><?= $row['name'] ?></td> </tr> <?php endforeach; ?> </tbody> </table>
内容的提问来源于stack exchange,提问作者itajackass
相关产品推荐
相关产品推荐

