APP下载

实现地址自动识别例项(PHP)

消息来源:baojiabao.com 作者: 发布时间:2024-11-01

报价宝综合消息实现地址自动识别例项(PHP)

文章正文

址自动识别现在普遍,特别是用在快递填写地址,姓名,手机号码的时候,会把这些按照一定的规范填写后,点选自动识别后,会自动填写到各自的input。最近也简单的实现了这个功能,给后台新增使用者的时候,自动识别地址。以下是效果图

具体问题具体分析!程式码实现基于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\']) 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-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都能想象到

"form-group">

{!! Form::label(\'discern\', \'自动识别地址:\',[\'class\' => \'control-label col-sm-2\']) !!}

"col-sm-5">

{!! Form::textarea(\'discern\', \'\', [\'class\' => \'form-textarea form-control form-discern\',\'rows\' => 3]) !!}

"col-sm-3" style="height: 75px;">

type="button" class="btn btn-info btn-sm discern" onclick="getDiscern();" >提交识别

"ruleGet" style="color: #676a74;">*检视模板

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);

}

}

})

}

整个过程简单,又清晰明了,以上就是小编的程式码,分享给大家,觉得哪个地方不对劲的,欢迎留言吐槽!

2019-12-29 00:51:00

相关文章