您的位置 首页 php

实现地址自动识别实例(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' ]) < $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);
}
}
})

}

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

文章来源:智云一二三科技

文章标题:实现地址自动识别实例(PHP)

文章地址:https://www.zhihuclub.com/79169.shtml

关于作者: 智云科技

热门文章

网站地图