
本文讲解如何将数据库查询逻辑封装在 php 函数中,避免直接输出(echo),改用返回数组方式,再在 html 模板中安全遍历渲染,实现关注点分离与代码可维护性。
本文讲解如何将数据库查询逻辑封装在 php 函数中,避免直接输出(echo),改用返回数组方式,再在 html 模板中安全遍历渲染,实现关注点分离与代码可维护性。
在 Web 开发中,将数据获取与页面呈现混写(如函数内直接 echo HTML 或字段值)会严重降低代码可读性、复用性与安全性。正确做法是:让数据层只负责获取并返回结构化数据,视图层(HTML)负责展示。下面以一个典型场景为例,逐步重构并说明最佳实践。
✅ 正确做法:函数返回数据,模板负责渲染
首先,修改 getData() 函数,使其不再执行 echo,而是收集所有结果并统一返回:
function getData() {
try {
$pdo = new PDO("mysql:host=localhost;dbname=db", 'root', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM table";
$stmt = $pdo->prepare($sql);
$stmt->execute();
// ✅ 收集全部结果为关联数组
return $stmt->fetchAll(PDO::FETCH_ASSOC); // 推荐:比 foreach 手动推入更简洁高效
} catch (PDOException $e) {
error_log("Database query failed: " . $e->getMessage()); // ❗生产环境应记录日志,而非直接 echo
return []; // 返回空数组,避免调用方崩溃
}
}? 提示:$stmt->fetchAll(PDO::FETCH_ASSOC) 直接返回所有行的关联数组,比手动 foreach + []= 更简洁、性能更优,且语义更清晰。
接着,在 HTML 模板中调用该函数,并在 <tbody> 内安全遍历渲染:
立即学习“PHP免费学习笔记(深入)”;
<table border="1">
<thead>
<tr>
<th>用户名</th>
<!-- 可根据实际字段添加更多列 -->
</tr>
</thead>
<tbody>
<?php
$users = getData(); // ✅ 获取数据,不产生任何输出
if (!empty($users)) {
foreach ($users as $row) { ?>
<tr>
<td><?php echo htmlspecialchars($row['username'] ?? ''); ?></td>
<!-- ✅ 使用 htmlspecialchars 防止 XSS 攻击 -->
</tr>
<?php }
} else { ?>
<tr>
<td colspan="1" style="text-align:center;">暂无用户数据</td>
</tr>
<?php } ?>
</tbody>
</table>⚠️ 关键注意事项
- 绝不混合职责:函数不应承担 HTML 输出责任;否则无法复用(如 API、JSON 响应、单元测试等场景均会失效)。
- 防御性输出:使用 htmlspecialchars() 转义用户数据,防止跨站脚本(XSS)漏洞;对可能缺失的键(如 $row['username'])使用空合并操作符 ?? '' 避免 Notice 错误。
- 错误处理要静默且健壮:生产环境中禁止 echo 错误详情(暴露敏感信息),应记录日志并返回默认值(如空数组)。
- PDO 连接建议复用或注入:当前示例每次调用都新建 PDO 实例,适合简单场景;高并发项目应使用连接池或依赖注入管理 PDO 实例生命周期。
✅ 总结
将数据获取与视图渲染解耦,是构建可维护 PHP 应用的基础原则。通过让 getData() 返回数组而非直接输出,你获得了:
- 更清晰的代码结构;
- 更强的复用能力(同一函数可用于表格、列表、JSON 接口等);
- 更好的安全性与错误控制;
- 更顺畅的测试路径(可对返回数组做断言,无需捕获输出缓冲)。
从今天起,牢记:函数返回数据,模板决定如何显示它。











