具体问题具体分析!代码实现基于laravel完成。一个laravel完整的功能得具备这些:路由route,Model, View, Controller, 我这里用的有依赖注入服务容器等功能,当然,用到地址,你首先要有地址库。。。
下面来看看是如何实现的,这里我只贴出核心代码
UsersController控制器
在这里新建构造函数,实现容器的依赖注入UsersRepository
/** @var UserRepository */ private $userRepository; public function __construct(UsersRepository $userRepo) { $this->userRepository = $userRepo; }
接下来就新建地址识别的方法, $discernDel 接收的数据是从前端传过来的,后面再贴前端代码。 业务代码处理交给容器UsersRepository里的方法getDiscern处理
/** * Function:地址识别 * Author:cyw0413 * @param Request $request * @return IlluminateContractsRoutingResponseFactory|IlluminateHttpResponse| * LaravelLumenHttpResponseFactory|SymfonyComponentHttpFoundationResponse */ public function getDiscern(Request $request) { $discernDel = $request->input(discernDel); try{ DB::beginTransaction(); $address = $this->userRepository->getDiscern($discernDel); DB::commit(); }catch (Exception $e){ DB::rollBack(); $msg = "信息提示:".$e->getMessage().",行:".$e->getLine(); return response([code => 0, msg=>$msg]); } return response([code=>1,msg=>$address]); //地址识别完成 }
来看看userRepository容器处理地址识别的各种业务代码
/** * Function:识别地址 * Author:cyw0413 */ public function getDiscern($discernDel) { if (empty($discernDel)) { throw new Exception("请传入要识别的地址"); } $discernDel_left = explode ([, $discernDel); if (!isset($discernDel_left[1])) { throw new Exception("你填写的地址规则错误,手机号码应该用[]"); } $discernDel_right = explode (], $discernDel_left[1]); if (!isset($discernDel_right[1]) || empty($discernDel_right[1])) { throw new Exception("你填写的地址规则错误,手机号码应该用[]"); } $name = $discernDel_left[0]; if (empty($name)) { throw new Exception("你填写的姓名有误!"); } $mobile = $discernDel_right[0]; if (empty($mobile) || checkMobile($mobile) == 0) { throw new Exception("你填写的手机号码格式有误!"); } $address = trim ($discernDel_right[1]); if (empty($address)) { throw new Exception("你填写的地址不能为空"); } $var_address = $this->getAddressArrar($address); $var_address[name] = $name; $var_address[mobile] = $mobile; return $var_address; }
上面的方法处理手机,名称,和地址处理,地址处理有些繁杂,因为有时候填写的地址有不一样的,比如广西省,有些就填写广西壮族自治区,所以getAddressArrar方法处理地址匹配信息,根据自己的业务做调整,如下
/** * Function:地址的处理 * Author:cyw0413 * @param $address * @return array * @throws Exception */ function getAddressArrar($address){ // 获取所有地址递归列表 $regions = $this->getRegions(); // 初始化数据 $province = $city = $district = []; // 先查找省份-第一级地区 $province = $this->checkAddress($address, $regions); if($province){ $province_arr = [110000,300000,404100,310000]; //4个市辖区如果地址不存在二级(市辖区,县),则特殊处理 if(!isset($province[region_code])){ throw new Exception("请正确填写省份(市辖区)"); } // 查找城市-第二级地区 $city = $this->checkAddress($address, $province[list]); //这里只处理4个市辖区,可能还有多种情况,待发现 if(in_array($province[region_code],$province_arr) && count($city[list]) == 0){ $city = $this->checkAddress(市辖区, $province[list]); if($city){ // 查找地区-第三级地区 $district = $this->checkAddress($address, $city[list]); //如果没有找到,则查找另外一个二级地区 if(!isset($district[region_code])){ $city = $this->checkAddress(县, $province[list]); // 查找地区-第三级地区 $district = $this->checkAddress($address, $city[list]); } } }else{ if($city){ // 查找地区-第三级地区 $district = $this->checkAddress($address, $city[list]); } } }else{ //省份不填,报错误 throw new Exception("省份没填写,请检查"); } return $this->getAddressInfo($address, $province, $city, $district); }
/** * 匹配正确的城市地址 * @param $address * @param $city_list * @param int $force * @param int $str_len * @return array **/ function checkAddress($address, $city_list, $force=false, $str_len=2){ $num = 0; $list = array(); $result = array(); // 遍历所有可能存在的城市 foreach ($city_list as $city_key=>$city){ $city_name = mb_substr($city[region_name], 0, $str_len,utf-8); // 判断是否存包含当前地址字符 $city_arr = explode($city_name, $address); // 如果存在相关字眼,保存该地址的所有子地址 if(count($city_arr) >= 2){ // 必须名称长度同时达到当前比对长度 if(strlen($city[region_name]) < $str_len){ continue; } $num ++; if(isset($city[child])){ $list = $list + $city[child]; } $result[] = array( region_code => $city_key, region_name => $city[region_name], list =>$list, ); } } // 如果有多个存在,则加大字符匹配长度 if($num > 1 || $force){ $region_name1 = $result[0][region_name]; $region_name2 = $result[1][region_name]; if(strlen($region_name1) == strlen($region_name2) && strlen($region_name1) == $str_len){ $region_id1 = $result[0][region_code]; $region_id2 = $result[1][region_code]; $index = $region_id1 > $region_id2 ? 1 : 0; $result = $result[$index]; return $result; } return $this->checkAddress($address, $city_list, $force, $str_len+1); } else { $result[0][list] = $list; return $result[0]; } }
/** * 根据原地址返回详细信息 * @param $address * @param $province * @param $city * @param $area * @return array **/ function getAddressInfo($address, $province, $city, $district){ // 查找最后出现的地址 - 截取详细信息 if(!isset($province[region_name])){ throw new Exception("请检查并正确填写省份(市辖区)"); } if(!isset($city[region_name])){ throw new Exception("请检查并正确填写城市"); } if(!isset($district[region_name])){ throw new Exception("请检查并正确填写区域(县/区/镇)"); } $find_str = ; if($province[region_name]){ $find_str = $province[region_name]; if($city[region_name]){ $find_str = $city[region_name]; if(isset($district[region_name]) && $district[region_name]){ $find_str = $district[region_name]; } } } // 截取详细的信息 $find_str_len = mb_strlen($find_str,utf-8); for($i=0; $i<$find_str_len-1; $i++){ $substr = mb_substr($find_str,0,$find_str_len - $i, utf-8); $end_index = mb_strpos($address, $substr); if ($end_index){ $address = mb_substr($address, $end_index + mb_strlen($substr) , mb_strlen($address) - $end_index); } } !empty($find_str) && $find_str = |S* . $find_str; $area[info] = preg_replace("/s*|,|,|:|:{$find_str}/i", , $address); if(empty($area[info])){ throw new Exception("详细地址不存在,请检查"); } return $address = [ province => $province[region_code], city => $city[region_code], district => $district[region_code], info => $area[info] ]; }
前端html部分代码
基本上能看得懂的。jquery用到 getDiscern();方法,手机号码,姓名,地址等input这里就不一一列出了。大家根据下面的jquery都能想象到
<div class="form-group"> {!! Form::label(discern, 自动识别地址:,[class => control-label col-sm-2]) !!} <div class="col-sm-5"> {!! Form::textarea(discern, , [class => form-textarea form-control form-discern,rows => 3]) !!} </div> <div class="col-sm-3" style="height: 75px;"> <button type="button" class="btn btn-info btn-sm discern" onclick="getDiscern();" >提交识别</button> <small class="ruleGet" style="color: #676a74;">*查看模板</small> </div> </div>
jquery代码部分
ajax post后交给url:getDiscern 处理,这个就是上面controller的方法,success返回的数据后再追加到每个input里,最后再清除掉自动识别地址框的数据
/** * 地址识别 * @returns {boolean} */ function getDiscern(){ var discernDel = $(".form-discern").val(); if(!discernDel){ alert("请输入要识别的地址"); return false; } $.ajax({ type: POST, url: "{!! route(admin.user.getDiscern) !!}", data: { _token: csrf_token(), discernDel: discernDel }, dataType: json, timeout: 50000, success: function (res) { if (res.code == 1) { $("input[name=addr[linkman]]").val(res.msg.name); $("input[name=user_name]").val(res.msg.mobile); $("input[name=addr[address]]").val(res.msg.info); //触发change事件 $(#province).val(res.msg.province).trigger(change); $(#city).val(res.msg.city).trigger(change); $(#area).val(res.msg.district).trigger(change); //识别后清除 $(".form-discern").val(""); } else { alert(res.msg); } } }) }