址自動識別現在普遍,特別是用在快遞填寫地址,姓名,手機號碼的時候,會把這些按照一定的規范填寫后,點擊自動識別后,會自動填寫到各自的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);
}
}
})
}
整個過程簡單,又清晰明了,以上就是小編的代碼,分享給大家,覺得哪個地方不對勁的,歡迎留言吐槽!