功能需求:用户输入混合收货地址,智能识别地址、手机、姓名。准备:需要两张表,一张面积表,一张姓氏表(面积表应该不难弄到,而且姓氏表来自中国,姓氏是自制的,表结构会附上bottom)思路:主要有两种思路,一种是用户正常输入完整地址,顺序按照地区级别匹配地址;另一种是用户输入异常(有遗漏),然后综合模糊查表,再根据结果比对原地址。温馨提示:手机端可以根据自己的需要修改regex;名字只匹配中文,可以根据自己的需要修改姓氏表和正则地址匹配。没有发现问题。效果图:代码:类文件getAddressArrar($address);//如果结果不理想,则模糊匹配if($result['level']!=3){$result_sub=$this->addressVague($address);//只有完全匹配才会被替换,否则不会做任何改变if($result_sub['level']==3){$result=$result_sub;}}//联系方式——优先匹配手机if(preg_match('/1\d{10}/',$address,$mobiles)){//手机$result['mobile']=$mobiles[0];}elseif(preg_match('/(\d{3,4}-)?\d{7,8}/',$address,$mobiles)){//固定电话$result['mobile']=$手机[0];}//识别名称-空间必须共享--probabilitiespreg_match_all('/[\x{4e00}-\x{9fa5}]{2,}/iu',$address,$names);如果($names){$name_where='';foreach($names[0]as$name){//必须多于1个字符且少于5个字符if(1getAll($names_sql);//计算有多少种可能性-名字$result['name_num']=count($list);如果($list){$name_first=$list[0]['name'];foreach($names[0]as$name){$len=mb_strlen($name_first,'utf-8');如果(mb_substr($name,0,$len,'utf-8')==$name_first){$result['name']=$name;}}}}}//去掉详情中的姓名和电话$result['info']=str_replace($result['mobile'],'',$result['info']);$result['info']=str_replace($result['name'],'',$result['info']);$result['info']=$result['province']['region_name']。$result['城市']['地区名称'].$结果['地区']['地区名称'].$结果['信息'];return$this->getCityLevelList($result);}/***获取对应的城市级别列表**/functiongetCityLevelList($result){//获取所有地址的递归列表$regions=$this->getRegionTreeList();//获取省份列表——只返回对应的列表$province_id=$result['province']['region_id'];如果($province_id){foreach($regionsas$region){unset($region['childs']);$result['province_list'][]=$region;}}//获取城市列表——只返回对应的列表$city_id=$result['city']['region_id'];如果($city_id){foreach($regions[$province_id]['childs']as$region){unset($region['childs']);$result['city_list'][]=$region;}}//获取地区列表——只有有值才会返回对应的列表$district_id=$result['district']['region_id'];if($district_id){foreach($regions[$province_id]['childs'][$city_id]['childs']as$region){unset($region['childs']);$result['district_list'][]=$region;}}return$result;}/***获取所有地址递归列表**/functiongetRegionTreeList(){//IO$file_name='地区.json';如果(is_file($file_name)){$regions=file_get_contents($file_name);$regions=json_decode($regions,true);}else{$region_sql="从区域中选择region_id,region_name,parent_id";$regions=Db::getInstance('DbTrade')->getAll($region_sql);$regions=$this->arrayKey($regions);file_put_contents($file_name,json_encode($regions));}return$regions;}/***第一种方法*根据地址列表递归查找准确地址*@param$address*@returnarray**/functiongetAddressArrar($address){//获取所有地址递归列表$regions=$this->getRegionTreeList();//初始化数据$province=$city=$district=array();//首先查找省份——一级地区$province=$this->checkAddress($address,$regions);if($province){//搜索城市-二级区域$city=$this->checkAddress($address,$province['list']);if($city){//搜索区域-三级区域//西藏自治区那曲市色尼区辽宁南路西藏公路第三个参数因为地址冲突所以必填。$district=$this->checkAddress($address,$city['list']);}}返回$this->getAddressInfo($address,$province,$city,$district);}/***第二种方法*地址模糊搜索**/functionaddressVague($address){$res=preg_match_all('/\S{2}[来自市、镇、县、乡、岛州]/iu',$地址,$arr);如果(!$res)返回假;$where='哪里';foreach($arr[0]as$value){if(strpos($value,'community')===false&&strpos($value,'开发区')===false){$where.="region_name像'%{$value}'或";}}$where=substr($where,0,-3);$region_sql="从区域中选择region_id,region_name,parent_id,region_type"。$在哪里;$citys=$GLOBALS['db']->getAll($region_sql);//匹配所有地址$result=array();foreach($citysas&$city){//所有关联的区域ID$city_ids=array();如果($city['region_type']==2){$city_ids=array($city['parent_id'],$city['region_id']);//尝试匹配第三层$region_sql="selectregion_id,region_name,parent_id,region_type,left(region_name,2)asab_namefromregionwhereparent_id='{$city['region_id']}'";$areas=$GLOBALS['db']->getAll($region_sql);foreach($areasas$row){if(mb_strpos($地址,$row['ab_name'])){$city_ids[]=$row['region_id'];}}}elseif($city['region_type']==3){$region_sql="selectparent_idfromregionwhereregion_id='{$city['parent_id']}'";$city['province_id']=$GLOBALS['db']->getOne($region_sql);$city_ids=array($city['parent_id'],$city['region_id'],$city['province_id']);}//查找该单词所有相关的区域记录$where="whereregion_idin(".join(',',$city_ids).")";$region_sql="selectregion_id,region_name,parent_id,region_type,left(region_name,2)asab_namefromregion".$在哪里。'按region_id升序排序';$city_list=$GLOBALS['db']->getAll($region_sql);排序($city_ids);$key=array_pop($city_ids);$result[$key]=$city_list;排序($结果);}if($result){list($province,$city,$area)=$result[0];返回$this->getAddressInfo($address,$province,$city,$area);}returnfalse;}/***匹配正确的城市地址*@param$address*@param$city_list*@paramint$force*@paramint$str_len*@return数组**/functioncheckAddress($address,$city_list,$force=false,$str_len=2){$num=0;$列表=数组();$结果=数组();//遍历所有可能的城市foreach($city_listas$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){继续;}$num++;$list=$list+$city['childs'];$result[]=array('region_id'=>$city['region_id'],'region_name'=>$city['region_name'],'list'=>$list,);}}//如果有多个,增加字符以匹配长度if($num>1||$force){$region_name1=$result[0]['region_name'];$region_name2=$result[1]['region_name'];如果(strlen($region_name1)==strlen($region_name2)&&strlen($region_name1)==$str_len){$region_id1=$result[0]['region_id'];$region_id2=$r结果[1]['region_id'];$index=$region_id1>$region_id2?1:0;$result=$result[$index];返回$结果;}返回$this->checkAddress($address,$city_list,$force,$str_len+1);}else{$result[0]['list']=$list;返回$结果[0];}}/***根据原始地址返回详细信息*@param$address*@param$province*@param$city*@param$area*@returnarray**/functiongetAddressInfo($address,$province,$city,$district){//查找最后一次出现的地址-拦截详细信息$find_str='';如果($province['region_name']){$find_str=$province['region_name'];如果($city['region_name']){$find_str=$city['region_name'];if($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);如果($end_index){$address=mb_substr($address,$end_index+mb_strlen($substr),mb_strlen($地址)-$end_index);}}!empty($find_str)&&$find_str='|\S*'。$find_str;$area['info']=preg_replace("/\s*|,|,|:|:{$find_str}/i",'',$address);$水平=0;if($district['region_name']){$level=3;}elseif($city['region_name']){$level=2;}elseif($province['region_name']){$level=1;}returnarray('province'=>array('region_id'=>$province['region_id'],'region_name'=>$province['region_name']),'city'=>array('region_id'=>$city['region_id'],'region_name'=>$city['region_name']),'district'=>array('region_id'=>$district['region_id'],'region_name'=>$district['region_name']),'info'=>$area['info'],'level'=>$level,);}/***递归所有地址组成无限分类数组*@param$data*@paramint$region_id*@returnarray**/functionarrayKey($data,$region_id=1){$result=array();}foreach($dataas$row){if($region_id==$row['parent_id']){$key=$row['region_id'];$行['通道ilds']=$this->arrayKey($data,$row['region_id']);$结果[$键]=$行;}}return$result;}}?>姓氏表(id,姓氏,优先匹配顺序)DROPTABLEIFEXISTS`surname`;CREATETABLE`surname`(`id`int(11)NOTNULLAUTO_INCREMENT,`name`char(10)CHARACTERSETutf8COLLATEutf8_general_ciNULLDEFAULTNULL,`sort`int(11)NULLDEFAULTNULL,PRIMARYKEY(`id`)USINGBTREE,INDEX`name`(`name`)使用BTREE,INDEX`sort`(`sort`)USINGBTREE)ENGINE=InnoDBAUTO_INCREMENT=481CHARACTERSET=utf8COLLATE=utf8_general_ciCOMMENT='姓氏表'ROW_FORMAT=Compact;地址region表CREATETABLE`region`(`region_id`smallint(5)UNSIGNEDNOTNULLAUTO_INCREMENT,`parent_id`smallint(5)UNSIGNEDNOTNULLDEFAULT0,`region_name`varchar(120)CHARACTERSETutf8COLLATEutf8_general_ciNOTNULLDEFAULT'',`region_type`tinyint(1)NOTNULLDEFAULT2,`agency_id`smallint(5)UNSIGNEDNOTNULLDEFAULT0,PRIMARYKEY(`region_id`)USINGBTREE,INDEX`parent_id`(`parent_id`)USINGBTREE,INDEX`region_type`(`region_type`)USINGBTREE,)ENGINE=InnoDBAUTO_INCREMENT=395