php 实现级联
实现级联的基本概念
级联(Cascading)通常指在表单或数据选择中,前一个选项的变化会影响后一个选项的内容。常见于省市区三级联动、分类层级选择等场景。PHP 实现级联通常结合前端(如 JavaScript/Ajax)和后端数据交互完成。
数据库设计示例
以省市区三级联动为例,数据库表结构可设计为:
CREATE TABLE `region` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`parent_id` int(11) DEFAULT NULL,
`level` tinyint(1) NOT NULL COMMENT '1:省, 2:市, 3:区',
PRIMARY KEY (`id`)
);
parent_id表示上级区域的 ID,顶级区域(如省份)的parent_id为NULL或0。
后端 PHP 代码实现
1. 获取级联数据的接口
// get_regions.php
header('Content-Type: application/json');
$parent_id = isset($_GET['parent_id']) ? (int)$_GET['parent_id'] : 0;
// 假设已连接数据库 ($pdo 为 PDO 对象)
$stmt = $pdo->prepare("SELECT id, name FROM region WHERE parent_id = ?");
$stmt->execute([$parent_id]);
$regions = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($regions);
2. 渲染初始页面
// index.php
$stmt = $pdo->prepare("SELECT id, name FROM region WHERE parent_id IS NULL");
$stmt->execute();
$provinces = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<select id="province">
<option value="">选择省份</option>
<?php foreach ($provinces as $province): ?>
<option value="<?= $province['id'] ?>"><?= $province['name'] ?></option>
<?php endforeach; ?>
</select>
<select id="city" disabled><option value="">选择城市</option></select>
<select id="district" disabled><option value="">选择区县</option></select>
前端 Ajax 交互
通过 JavaScript 监听 select 变化并请求数据:

document.getElementById('province').addEventListener('change', function() {
const provinceId = this.value;
const citySelect = document.getElementById('city');
if (!provinceId) {
citySelect.disabled = true;
citySelect.innerHTML = '<option value="">选择城市</option>';
return;
}
fetch(`get_regions.php?parent_id=${provinceId}`)
.then(response => response.json())
.then(data => {
citySelect.disabled = false;
citySelect.innerHTML = '<option value="">选择城市</option>' +
data.map(city => `<option value="${city.id}">${city.name}</option>`).join('');
});
});
// 类似逻辑实现 city -> district 的级联
document.getElementById('city').addEventListener('change', function() {
const cityId = this.value;
const districtSelect = document.getElementById('district');
if (!cityId) {
districtSelect.disabled = true;
districtSelect.innerHTML = '<option value="">选择区县</option>';
return;
}
fetch(`get_regions.php?parent_id=${cityId}`)
.then(response => response.json())
.then(data => {
districtSelect.disabled = false;
districtSelect.innerHTML = '<option value="">选择区县</option>' +
data.map(district => `<option value="${district.id}">${district.name}</option>`).join('');
});
});
优化与扩展
-
数据缓存
频繁请求的数据可通过 Redis 或文件缓存减少数据库查询。 -
一次性加载所有数据
若数据量较小,可一次性返回所有层级数据,前端通过 JavaScript 过滤实现级联,减少 HTTP 请求。
-
框架集成
在 Laravel 等框架中,可通过路由、控制器和 Blade 模板更优雅地实现:// Laravel 路由 Route::get('/regions', 'RegionController@index'); -
安全性
对输入的parent_id进行校验,避免 SQL 注入。
其他场景示例
分类层级级联
// 递归获取分类树
function getCategoryTree($parent_id = 0) {
$stmt = $pdo->prepare("SELECT id, name FROM categories WHERE parent_id = ?");
$stmt->execute([$parent_id]);
$categories = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($categories as &$category) {
$category['children'] = getCategoryTree($category['id']);
}
return $categories;
}
通过结合前后端交互和数据库设计,PHP 可以灵活实现多种级联功能。






