实现地址自动识别实例(PHP)
具体问题具体分析!代码实现基于laravel完成。一个laravel完整的功能得具备这些:路由route,Model, View, Controller, 我这里用的有依赖注入服务容器等功能,当然,用到地址,你首先要有地址库。。。
下面来看看是如何实现的,这里我只贴出核心代码
UsersController控制器
在这里新建构造函数,实现容器的依赖注入UsersRepository
/**@varUserRepository */
private$userRepository;
publicfunction__construct(UsersRepository $userRepo)
{
$this->userRepository = $userRepo;
}
接下来就新建地址识别的方法, $discernDel接收的数据是从前端传过来的,后面再贴前端代码。 业务代码处理交给容器UsersRepository里的方法getDiscern处理
/**
* Function:地址识别
* Author:cyw0413
*@paramRequest $request
*@returnIlluminateContractsRoutingResponseFactory|IlluminateHttpResponse|
* LaravelLumenHttpResponseFactory|SymfonyComponentHttpFoundationResponse
*/
publicfunctiongetDiscern(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();
returnresponse(['code'=>0,'msg'=>$msg]);
}
returnresponse(['code'=>1,'msg'=>$address]);//地址识别完成
}
来看看userRepository容器处理地址识别的各种业务代码
/**
* Function:识别地址
* Author:cyw0413
*/
publicfunctiongetDiscern($discernDel)
{
if(empty($discernDel)) {
thrownewException("请传入要识别的地址");
}
$discernDel_left = explode ('[', $discernDel);
if(!isset($discernDel_left[1])) {
thrownewException("你填写的地址规则错误,手机号码应该用[]");
}
$discernDel_right = explode (']', $discernDel_left[1]);
if(!isset($discernDel_right[1]) ||empty($discernDel_right[1])) {
thrownewException("你填写的地址规则错误,手机号码应该用[]");
}
$name = $discernDel_left[0];
if(empty($name)) {
thrownewException("你填写的姓名有误!");
}
$mobile = $discernDel_right[0];
if(empty($mobile) || checkMobile($mobile) ==0) {
thrownewException("你填写的手机号码格式有误!");
}
$address = trim ($discernDel_right[1]);
if(empty($address)) {
thrownewException("你填写的地址不能为空");
}
$var_address =$this->getAddressArrar($address);
$var_address['name'] = $name;
$var_address['mobile'] = $mobile;
return$var_address;
}
上面的方法处理手机,名称,和地址处理,地址处理有些繁杂,因为有时候填写的地址有不一样的,比如广西省,有些就填写广西壮族自治区,所以getAddressArrar方法处理地址匹配信息,根据自己的业务做调整,如下
/**
* Function:地址的处理
* Author:cyw0413
*@param$address
*@returnarray
*@throwsException
*/
functiongetAddressArrar($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'])){
thrownewException("请正确填写省份(市辖区)");
}
// 查找城市-第二级地区
$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{
//省份不填,报错误
thrownewException("省份没填写,请检查");
}
return$this->getAddressInfo($address, $province, $city, $district);
}
/**
* 匹配正确的城市地址
*@param$address
*@param$city_list
*@paramint $force
*@paramint $str_len
*@returnarray
**/
functioncheckAddress($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
*@returnarray
**/
functiongetAddressInfo($address, $province, $city, $district){
// 查找最后出现的地址 - 截取详细信息
if(!isset($province['region_name'])){
thrownewException("请检查并正确填写省份(市辖区)");
}
if(!isset($city['region_name'])){
thrownewException("请检查并正确填写城市");
}
if(!isset($district['region_name'])){
thrownewException("请检查并正确填写区域(县/区/镇)");
}
$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'])){
thrownewException("详细地址不存在,请检查");
}
return$address = [
'province'=> $province['region_code'],
'city'=> $city['region_code'],
'district'=> $district['region_code'],
'info'=> $area['info']
];
}
前端html部分代码
基本上能看得懂的。jquery用到 getDiscern();方法,手机号码,姓名,地址等input这里就不一一列出了。大家根据下面的jquery都能想象到
{!! Form::label('discern','自动识别地址:',['class'=>'control-label col-sm-2']) !!}
{!! Form::textarea('discern','', ['class'=>'form-textarea form-control form-discern','rows'=> 3]) !!}
提交识别
*查看模板
jquery代码部分
ajax post后交给url:getDiscern 处理,这个就是上面controller的方法,success返回的数据后再追加到每个input里,最后再清除掉自动识别地址框的数据
/**
* 地址识别
* @returns {boolean}
*/
functiongetDiscern(){
vardiscernDel = $(".form-discern").val();
if(!discernDel){
alert("请输入要识别的地址");
returnfalse;
}
$.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);
}
}
})
}
整个过程简单,又清晰明了,以上就是小编的代码,分享给大家,觉得哪个地方不对劲的,欢迎留言吐槽!