123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- <?php
- declare (strict_types=1);
- namespace library\utils;
- use think\facade\Config;
- use think\facade\Db;
- use think\facade\Lang;
- use think\Response;
- class Region
- {
- public $data = [];
- public function __construct()
- {
- $this->data = $this->getData();
- }
- /**
- * 通过子集获取,全部父级
- * @param int $id
- * @param string $file 全部父级字段
- * @param string $Division 分割线
- */
- public function getParentS($id = 0, $file = '*', $Division = '')
- {
- $tAr = [];
- $rAr = [];
- while (true) {
- $data = $this->getParent($id);
- if (empty($data)) {
- break;
- }
- if (!empty($data)) {
- $tAr[] = $data;
- $id = $data['ParentId'];
- }
- }
- $tAr = array_reverse($tAr);
- foreach ($tAr as $v) {
- $rAr[] = ($file == '*' ? $v : $v[$file]);
- }
- if ($file != '*' && $Division != '')
- return join($Division, $rAr);
- else
- return $rAr;
- }
- /**
- * 获取子集所以Id
- * @param $id
- */
- public function getChildIds($id)
- {
- $rAr = $this->getChilds($id);
- return array_column($rAr, 'ID');
- }
- /**
- * 获取子集数据
- * @param int $id
- */
- public function getChild($id = 0)
- {
- $rAr = [];
- foreach ($this->data as $v) {
- if ($v['ParentId'] == $id) $rAr[] = $v;
- }
- return $rAr;
- }
- /**
- * 数据
- * @param int $id
- * @return array
- */
- public function getChilds($id = 0)
- {
- $data = $this->getChild($id);
- foreach ($data as $v) {
- $d = $this->getChilds($v['ID']);
- $data = array_merge($data, $d);
- }
- return $data;
- }
- /**
- * 上一层数
- * @param int $parentId
- * @param string $file 字段
- */
- public function getParent($parentId = 0, $file = '*')
- {
- foreach ($this->data as $v) {
- if ($v['ID'] == $parentId) return ($file == '*' ? $v : $v[$file]);
- }
- return null;
- }
- /**
- * 获取层级数据
- * @param int $lIndex
- */
- public function getLevel($lIndex = 0)
- {
- $rAr = [];
- foreach ($this->data as $v) {
- if ($v['LevelType'] == $lIndex) $rAr[] = $v;
- }
- return $rAr;
- }
- /**
- * 模糊搜索ID
- * @param $name
- * @param string $file
- * @param int $parentId 上一层ID
- * @return mixed|null
- */
- public function getLike($name, $file = '*', $parentId = -1)
- {
- if (empty($name)) return null;
- if ($parentId == -1)
- $data = $this->data;
- else
- $data = $this->getChilds($parentId);
- foreach ($data as $v) {
- if (strpos($v['Name'], $name) !== false) {
- return ($file == '*' ? $v : $v[$file]);
- }
- }
- return null;
- }
- /**
- * 获取地址到ID
- * @param $region
- */
- public function getLikeS($name)
- {
- if (empty($name)) return 0;
- $nameAr = explode('-', $name);
- $province = 0;
- $city = 0;
- $area = 0;
- if (!empty($nameAr)) {
- $province = $this->getLike($nameAr[0], 'ID');
- }
- if (count($nameAr) > 1) {
- $city = $this->getLike($nameAr[1], 'ID', $province);
- }
- if (count($nameAr) > 2) {
- $area = $this->getLike($nameAr[1], 'ID', $province);
- }
- if (!empty($area)) return $area;
- if (!empty($city)) return $city;
- if (!empty($province)) return $province;
- return 0;
- }
- /**
- * 查询地址信息
- * @param type $id
- * @param type $file
- * @return type
- */
- public function getField($id, $file = '*')
- {
- foreach ($this->data as $v) {
- if ($v['ID'] == $id) {
- return ($file == '*' ? $v : $v[$file]);
- }
- }
- return null;
- }
- public function getRegion($str)
- {
- $province = [];
- $city = [];
- $area = [];
- //省份获取
- foreach ($this->data as $v) {
- $item = $v;
- $strLen = strpos($str, $item['ProvinceShortName']);
- if ($item['LevelType'] == 1 && $strLen !== false && (empty($province) || $province['len'] > $strLen)
- ) {
- $v['len'] = $strLen;
- $v['len2'] = strlen($item['ProvinceShortName']);
- $province = $v;
- }
- }
- //城市列表
- if (!empty($province)) {
- $data = $this->getChild($province['ID']);
- if (count($data) == 1) {
- $city = $data[0];
- $city['len'] = 0;
- } else {
- //匹配城市 | 地址前面优先匹配
- $pLen = -1;
- foreach ($data as $v) {
- $str2 = substr($str . '-', $province['len'] + $province['len2'], -1);
- $strLen = strpos($str2, empty($v['CityShortName']) ? '' : $v['CityShortName']);
- if ($strLen !== false && $pLen == -1) {
- $pLen = $strLen;
- }
- if ($strLen !== false && $strLen <= $pLen && $v['LevelType'] == 2) {
- $v['len'] = $strLen + $province['len'];
- $city = $v;
- $pLen = $strLen;
- }
- }
- //可能城市和省会一样检测
- if (empty($city)) {
- foreach ($data as $v) {
- $strLen = strpos($str, empty($v['CityShortName']) ? '' : $v['CityShortName']);
- if ($strLen !== false && $v['LevelType'] == 2) {
- $v['len'] = $strLen;
- $city = $v;
- break;
- }
- }
- }
- }
- }
- //地区数据
- if (!empty($city)) {
- $data = $this->getChild($city['ID']);
- foreach ($data as $v) {
- $item = $v;
- $strLen = strpos($str, empty($item['DistrictShortName']) ? '' : $item['DistrictShortName']);
- if ($strLen !== false) {
- $v['len'] = $strLen;
- $area = $v;
- }
- }
- }
- //地区
- foreach ($this->data as $v) {
- $item = $v;
- $strLen = strpos($str, $item['ProvinceShortName']);
- if ($item['LevelType'] == 3 && $strLen !== false && empty($city) &&
- (empty($area) || $area['len'] < $strLen)
- ) {
- $v['len'] = $strLen;
- $area = $v;
- }
- }
- //////////// 详情地址 ////////////
- //省份
- if (!empty($province)) {
- $len = strpos($str, $province['Name']);
- $name = $province['ProvinceShortName'];
- if ($len !== false && $len == $province['len']) {
- $name = $province['Name'];
- }
- $str = $this->strReplaceLimit($name, '', $str, 1);
- }
- //城市列表
- if (!empty($city)) {
- $len = strpos($str, $city['Name']);
- $name = $city['CityShortName'];
- if ($len !== false) {
- $name = $city['Name'];
- }
- $str = $this->strReplaceLimit($name, '', $str, 1);
- }
- //城市列表
- if (!empty($area)) {
- $len = strpos($str, $area['Name']);
- $name = $area['DistrictShortName'];
- if ($len !== false) {
- $name = $area['Name'];
- }
- $str = $this->strReplaceLimit($name, '', $str, 1);
- }
- //var_dump(['address'=>trim($str),'province'=> empty($province) ? '' : $province['Name'],'city'=> empty($city) ? '' : $city['Name'],'area'=>empty($area) ? '' : $area['Name']]);
- return ['address' => trim($str), 'province' => empty($province) ? '' : $province['Name'], 'city' => empty($city) ? '' : $city['Name'], 'area' => empty($area) ? '' : $area['Name']];
- }
- /**
- * 获取基础数据【缓存数据】
- */
- private function getData()
- {
- $data = cache('region');
- if (empty($data)) {
- $data = Db::name("region")->field("ID,ParentId,LevelType,Name,Pinyin,ProvinceShortName,DistrictShortName,CityShortName")->select()->toArray();
- cache('region', $data);
- }
- return $data;
- }
- /**
- * @param $method
- * @param $args
- * @return mixed
- */
- public static function __callStatic($method, $args)
- {
- $model = new static();
- return call_user_func_array([$model, $method], $args);
- }
- /**
- * $search:要替换的字符串或者数组
- * $replace:要替换的值
- * $subject:要替换的文本
- * $limit:替换的此数字
- * @return string|string[]|null
- */
- function strReplaceLimit($search, $replace, $subject, $limit = -1)
- {
- if (is_array($search)) {
- foreach ($search as $k => $v) {
- $search[$k] = '`' . preg_quote($search[$k], '`') . '`';
- }
- } else {
- $search = '`' . preg_quote($search, '`') . '`';
- }
- return preg_replace($search, $replace, $subject, $limit);
- }
- }
|