<dd draggable='idd2fp'></dd>

            <sub dir='4h2mcf1'></sub>

              文章熱詞:php,地址自動識别

              日期:2019-06-14 09:03 by 楊國偉 1245 1 收藏
              我要分享

              摘要:地址自動識别現在普遍,特别是用在快遞填寫地址,姓名,手機号碼的時候,會把這些按照一定的規範填寫後,點擊自動識别後,會自動填寫到各自的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使用curl并發減少後端訪問時間的方法

              下一篇:git的4個階段的撤銷更改你必須要弄懂


              評論