用 PHP 简单实现地址自动识别功能
在现代化的开发中,地址自动识别已经成为一个非常常见的功能。特别是在快递填写地址时,系统会根据输入的内容自动识别地址、姓名、手机号码等信息,并自动填充到相应的输入框中。这不仅提高了用户体验,还减少了手动输入的错误概率。
实现思路
我们使用 Laravel 框架来实现这个功能,主要涉及到以下几个部分:
- 路由 (Route)
- 模型 (Model)
- 视图 (View)
- 控制器 (Controller)
1. 控制器实现
在 UsersController
控制器中,我们通过依赖注入将 UsersRepository
注入到控制器中,方便处理用户相关的业务逻辑。以下是控制器的核心代码:
/** @var UserRepository */
private $userRepository;
public function __construct(UsersRepository $userRepo) {
$this->userRepository = $userRepo;
}
地址识别方法
$discernDel
是从前端传递过来的地址信息。业务逻辑的处理通过 UsersRepository
中的方法 getDiscern
实现:
/**
* Function: 地址识别
*/
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]); // 地址识别完成
}
2. 业务逻辑处理
在 UsersRepository
中,我们处理地址识别的业务逻辑。getDiscern
方法负责解析输入的姓名、手机号码、地址等信息:
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;
}
3. 地址匹配处理
getAddressArrar
方法处理复杂的地址格式。例如不同地区的名称可能会有所不同(如 "广西省" 和 "广西壮族自治区"),需要进行灵活的匹配。
function getAddressArrar($address) {
// 获取所有地址递归列表
$regions = $this->getRegions();
$province = $city = $district = [];
// 查找省份
$province = $this->checkAddress($address, $regions);
if ($province) {
// 特殊市辖区处理
if (in_array($province['region_code'], ['110000', '300000', '404100', '310000']) && 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);
}
4. 前端实现
前端使用了简单的表单输入和按钮触发 Ajax 请求,将用户输入的地址信息发送到后台进行识别:
<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>
5. 前端 JavaScript
在前端,使用 jQuery 实现了 Ajax 提交,地址识别结果会填充到对应的输入框中:
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);
}
}
});
}
总结
地址自动识别功能的实现过程其实非常简单,核心思路是通过正则匹配和递归遍历地址库,实现对地址、姓名、手机号码等信息的自动识别和填充。这种功能不仅提升了用户体验,还减少了手动输入的工作量。在 Laravel 框架中,通过依赖注入、前后端交互和数据库操作,可以非常方便地实现这个功能。