PHP实现省市区查询的方法:1、设计一张数据表;2、根据查询的id查找相对应的parent_id;3、通过“function GetCityInfo(searstr, cityselect) {...}”等代码实现省市区查询即可。
本文操作环境:Windows7系统,PHP7.1版,Dell G3电脑。
联动查询
什么是联动查询,其实这个东西在生活中非常常见,比如网购(这个几乎人人都用过吧),在网购的时候,我们需要填写订单信息,信息中有一项需要填写地址的地方,有的网站则用的是联动查询,节省了用户填写订单的时间,这时候联动查询就排上用场了,比如当我们在省下拉框中选择:河北省,相对应的市区就需要改变里面的信息,将相对应的市区加载到下拉框里面,贴个图片
数据库设计
设计一张表,然后这张表循环查询自己,根据查询的id查找相对应的parent_id,就能够查询到想要的结果,最后两个字段是冗余字段,可要可不要,根据自己项目需求
创建数据库的语句如下,数据库为MysqL数据库
CREATE TABLE `china_area` ( `id` int(11) NOT NULL, `parent_id` int(11) NOT NULL DEFAULT '0', `code` varchar(10) NOT NULL, `name` varchar(191) NOT NULL, `created_at` timestamp NULL DEFAULT NULL, `updated_at` timestamp NULL DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;
简单插入一些数据,完整表数据很大,大概三千多行,这里就不展示所有的数据代码了,免得华而不实,想要这些数据的话,可以去网上找一下,或者自己设计,我也上传了一份,但是需要积分
INSERT INTO `china_area` (`id`, `parent_id`, `code`, `name`, `created_at`, `updated_at`) VALUES(1, 0, '110000', '北京市', NULL, NULL),(2, 0, '120000', '天津市', NULL, NULL),(3, 0, '130000', '河北省', NULL, NULL),(4, 0, '140000', '山西省', NULL, NULL),(5, 0, '150000', '内蒙古自治区', NULL, NULL),(6, 0, '210000', '辽宁省', NULL, NULL),(7, 0, '220000', '吉林省', NULL, NULL),(8, 0, '230000', '黑龙江省', NULL, NULL),(9, 0, '310000', '上海市', NULL, NULL),(10, 0, '320000', '江苏省', NULL, NULL),(11, 0, '330000', '浙江省', NULL, NULL),(12, 0, '340000', '安徽省', NULL, NULL),(13, 0, '350000', '福建省', NULL, NULL),(14, 0, '360000', '江西省', NULL, NULL),(15, 0, '370000', '山东省', NULL, NULL),(16, 0, '410000', '河南省', NULL, NULL),(17, 0, '420000', '湖北省', NULL, NULL),(18, 0, '430000', '湖南省', NULL, NULL),(19, 0, '440000', '广东省', NULL, NULL),(20, 0, '450000', '广西壮族自治区', NULL, NULL),(21, 0, '460000', '海南省', NULL, NULL),(22, 0, '500000', '重庆市', NULL, NULL),(23, 0, '510000', '四川省', NULL, NULL),(24, 0, '520000', '贵州省', NULL, NULL),(25, 0, '530000', '云南省', NULL, NULL),(26, 0, '540000', '西藏自治区', NULL, NULL),(27, 0, '610000', '陕西省', NULL, NULL),(28, 0, '620000', '甘肃省', NULL, NULL),(29, 0, '630000', '青海省', NULL, NULL),(30, 0, '640000', '宁夏回族自治区', NULL, NULL),(31, 0, '650000', '新疆维吾尔自治区', NULL, NULL),(32, 0, '710000', '台湾省', NULL, NULL),(33, 0, '810000', '香港特别行政区', NULL, NULL),(34, 0, '820000', '澳门特别行政区', NULL, NULL),(35, 1, '110100', '北京城区', NULL, NULL),(36, 35, '110101', '东城区', NULL, NULL),(37, 35, '110102', '西城区', NULL, NULL),(38, 35, '110105', '朝阳区', NULL, NULL),(39, 35, '110106', '丰台区', NULL, NULL),(40, 35, '110107', '石景山区', NULL, NULL),(41, 35, '110108', '海淀区', NULL, NULL),(42, 35, '110109', '门头沟区', NULL, NULL),(43, 35, '110111', '房山区', NULL, NULL),(44, 35, '110112', '通州区', NULL, NULL),(45, 35, '110113', '顺义区', NULL, NULL),(46, 35, '110114', '昌平区', NULL, NULL),(47, 35, '110115', '大兴区', NULL, NULL),(48, 35, '110116', '怀柔区', NULL, NULL),(49, 35, '110117', '平谷区', NULL, NULL),(50, 35, '110118', '密云区', NULL, NULL),(51, 35, '110119', '延庆区', NULL, NULL),(52, 2, '120100', '天津城区', NULL, NULL),(53, 52, '120101', '和平区', NULL, NULL),(54, 52, '120102', '河东区', NULL, NULL),(55, 52, '120103', '河西区', NULL, NULL),(56, 52, '120104', '南开区', NULL, NULL),(57, 52, '120105', '河北区', NULL, NULL),(58, 52, '120106', '红桥区', NULL, NULL),(59, 52, '120110', '东丽区', NULL, NULL),(60, 52, '120111', '西青区', NULL, NULL),(61, 52, '120112', '津南区', NULL, NULL),(62, 52, '120113', '北辰区', NULL, NULL),(63, 52, '120114', '武清区', NULL, NULL),(64, 52, '120115', '宝坻区', NULL, NULL),(65, 52, '120116', '滨海新区', NULL, NULL),(66, 52, '120117', '宁河区', NULL, NULL),(67, 52, '120118', '静海区', NULL, NULL),(68, 52, '120119', '蓟州区', NULL, NULL),(69, 3, '130100', '石家庄市', NULL, NULL),(70, 3, '130200', '唐山市', NULL, NULL),(71, 3, '130300', '秦皇岛市', NULL, NULL),(72, 3, '130400', '邯郸市', NULL, NULL),(73, 3, '130500', '邢台市', NULL, NULL),(74, 3, '130600', '保定市', NULL, NULL),(75, 3, '130700', '张家口市', NULL, NULL),(76, 3, '130800', '承德市', NULL, NULL),(77, 3, '130900', '沧州市', NULL, NULL),(78, 3, '131000', '廊坊市', NULL, NULL),(79, 3, '131100', '衡水市', NULL, NULL),(80, 69, '130102', '长安区', NULL, NULL),(81, 69, '130104', '桥西区', NULL, NULL),(82, 69, '130105', '新华区', NULL, NULL),(83, 69, '130107', '井陉矿区', NULL, NULL),(84, 69, '130108', '裕华区', NULL, NULL),(85, 69, '130109', '藁城区', NULL, NULL),(86, 69, '130110', '鹿泉区', NULL, NULL),(87, 69, '130111', '栾城区', NULL, NULL),(88, 69, '130121', '井陉县', NULL, NULL),(89, 69, '130123', '正定县', NULL, NULL),(90, 69, '130125', '行唐县', NULL, NULL),(91, 69, '130126', '灵寿县', NULL, NULL),(92, 69, '130127', '高邑县', NULL, NULL),(93, 69, '130128', '深泽县', NULL, NULL),(94, 69, '130129', '赞皇县', NULL, NULL),(95, 69, '130130', '无极县', NULL, NULL);
数据库大致就是这样,通过上一级的id然后查找和parent_id对应的值找出相对应的数据,循环查找,三级联动查找两次就能找到相对应的结果,闲话少叙,下面开始讲明思路。
设计思路
第一个下拉框(也就是省份)是再页面初始化的时候加载出来的,所以不用异步加载,第二个(市)和第三个(县,区)是异步加载出来的,然后当用户下拉框操作之后通过js事件发送Ajax请求获取后台代码,然后后台根据传过来的parent_id(页面传输尽量不要用数据库里面的字段)的值进行查找,数据库查询代码如下
SELECT * FROM `china_area` WHERE parent_id=.$_GET['precityid']
然后将结果拼接成json发送给前台,然后用js拼接结果。
代码实现
第一个下拉框在在页面加载的时候直接生成可以直接生成,市和县只需要添加select标签即可,不用添加相对应的数据,这里默认没有选选择的下拉框用的value值是-1
<p class=row>//引用了bootstrap框架和jq库,节省代码 <p class=col-xs-2 bg-success col-xs-offset-3> <select class=form-control province> <option value=-1>请选择...</option> <?PHP $conn = MysqLi_connect(localhost, root, , zbt);//省份下拉框,可以在页面刚加载的时候生成 MysqLi_query($conn, set names utf8); $sqlstr = SELECT * FROM `china_area` WHERE parent_id =0; $result = MysqLi_query($conn, $sqlstr); while ($myrow = MysqLi_fetch_array($result)) {?> <option value=<?PHP echo $myrow[0] ?>><?PHP echo $myrow[3] ?></option> <?PHP } ?> </select> </p> <p class=col-xs-2 bg-success> <select class=form-control city><!--市区下拉框--> </select> </p> <p class=col-xs-2 bg-success> <select class=form-control county><!--县级下拉框--> </select> </p></p>
HTML代码就那么多,接下来就是js代码,这里我引用了bootstrap框架和jQuery库(不知道能不能说是框架),jq帮我们封装好了很多方法,直接用就行,闲话少说,直接上代码
<script> $(function() { $(.province).change(function() { //省份下拉框事件 var citysele = $(.city);//获取要改变的下一个下拉框 GetCityInfo(precityid= + $(this).val(), citysele); }); $(.city).change(function() { //市区下拉框事件 var citysele = $(.county); GetCityInfo(precityid= + $(this).val(), citysele); }); $(.county).change(function() { //弹出结果 alert(您选择的城市是: + $(.province option:selected).text() + + $(.city option:selected).text() + + $(.county option:selected).text()) }); function GetCityInfo(searstr, cityselect) {//两个参数,第一个是搜索字符串,第二个是相对应的下一个要变动的下拉框 let sendtourl = encodeURI(conn.PHP? + searstr); $.ajax({ type: GET, url: sendtourl, dataType: json, success: function(data) { cityselect.empty(); if (data.data.length <= 0) { var option = <option>暂无数据</option>;//没有数据 cityselect.append(option); return; } cityselect.append(<option value='-1'>请选择...</option>);//执行到这里就是有数据,将数据添加到相对应的下拉框 for (var i = 0; i < data.data.length; i++) { var option = <option value= + data.data[i].id + > + data.data[i].name + </option>; cityselect.append(option); } }, error: function(xhr) { alert(error + xhr.status); } }); } })</script>
代码写的有点low,不过能用就行,有时候可能或出现写的js代码没有运行的现象,给个提示,js代码最好放在页面最后面,接下来设计后台查询数据库的PHP代码,直接上代码
<?PHP header('Content-Type:application/json');if (!isset(getallheaders()['Referer'])) exit;//不是自己的网址不返回数据$conn=MysqLi_connect(localhost,root,,zbt); MysqLi_query($conn,set names utf8);if (isset($_GET['precityid'])) { $sqlstr=SELECT * FROM `china_area` WHERE parent_id=.$_GET['precityid'];//根据前台的数据查询相对应的表 $result=MysqLi_query($conn,$sqlstr); $datas=array(); while($myrow=MysqLi_fetch_array($result)){ $rows=array(); $rows[id]=$myrow[0]; $rows[parent_id]=$myrow[1]; $rows[code]=$myrow[2]; $rows['name']=$myrow[3]; array_push($datas,$rows); $rows=; }//拼接结果 $data=array(); $data[code]=200;//状态码 $data[msg]=getallheaders()['Referer'];//自定义消息,我是为了看一下Referer是否正确,这里可以删除 $data[data]=$datas; echo json_encode($data,JSON_UnesCAPED_UNICODE);}?>
可以了,将项目放到服务器上运行
总结
效果还行,当然了,这只是学习使用,真正的应用到实际环境肯定比这要复杂,如果觉得不错,可以一键三连
推荐学习:《PHP教程》