Region.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. <?php
  2. declare (strict_types = 1);
  3. namespace library\utils;
  4. use think\facade\Config;
  5. use think\facade\Db;
  6. use think\facade\Lang;
  7. use think\Response;
  8. class Region
  9. {
  10. public $data = [];
  11. public function __construct()
  12. {
  13. $this->data = $this->getData();
  14. }
  15. /**
  16. * 通过子集获取,全部父级
  17. * @param int $id
  18. * @param string $file 全部父级字段
  19. * @param string $Division 分割线
  20. */
  21. public function getParentS($id = 0,$file = '*',$Division = ''){
  22. $tAr = [];
  23. $rAr = [];
  24. while (true){
  25. $data = $this->getParent($id);
  26. if(empty($data)){
  27. break;
  28. }
  29. if(!empty($data)){
  30. $tAr[] = $data;
  31. $id = $data['ParentId'];
  32. }
  33. }
  34. $tAr = array_reverse($tAr);
  35. foreach ($tAr as $v){
  36. $rAr[] = ($file == '*' ? $v : $v[$file]);
  37. }
  38. if($file != '*' && $Division != '')
  39. return join($Division,$rAr);
  40. else
  41. return $rAr;
  42. }
  43. /**
  44. * 获取子集所以Id
  45. * @param $id
  46. */
  47. public function getChildIds($id){
  48. $rAr = $this->getChilds($id);
  49. return array_column($rAr, 'ID');
  50. }
  51. /**
  52. * 获取子集数据
  53. * @param int $id
  54. */
  55. public function getChild($id = 0){
  56. $rAr = [];
  57. foreach ($this->data as $v){
  58. if($v['ParentId'] == $id) $rAr[] = $v;
  59. }
  60. return $rAr;
  61. }
  62. /**
  63. * 数据
  64. * @param int $id
  65. * @return array
  66. */
  67. public function getChilds($id = 0){
  68. $data = $this->getChild($id);
  69. foreach ($data as $v){
  70. $d = $this->getChilds($v['ID']);
  71. $data = array_merge($data,$d);
  72. }
  73. return $data;
  74. }
  75. /**
  76. * 上一层数
  77. * @param int $parentId
  78. * @param string $file 字段
  79. */
  80. public function getParent($parentId = 0,$file ='*'){
  81. foreach ($this->data as $v){
  82. if($v['ID'] == $parentId) return ($file == '*' ? $v : $v[$file]);
  83. }
  84. return null;
  85. }
  86. /**
  87. * 获取层级数据
  88. * @param int $lIndex
  89. */
  90. public function getLevel($lIndex = 0){
  91. $rAr = [];
  92. foreach ($this->data as $v){
  93. if($v['LevelType'] == $lIndex) $rAr[] = $v;
  94. }
  95. return $rAr;
  96. }
  97. /**
  98. * 模糊搜索ID
  99. * @param $name
  100. * @param string $file
  101. * @return mixed|null
  102. */
  103. public function getLike($name,$file ='*') {
  104. if(empty($name)) return null;
  105. foreach ($this->data as $v) {
  106. if(strpos($v['Name'],$name) !== false) {
  107. return ($file == '*' ? $v : $v[$file]);
  108. }
  109. }
  110. return null;
  111. }
  112. /**
  113. * 查询地址信息
  114. * @param type $id
  115. * @param type $file
  116. * @return type
  117. */
  118. public function getField($id,$file ='*') {
  119. foreach ($this->data as $v) {
  120. if($v['ID'] == $id) {
  121. return ($file == '*' ? $v : $v[$file]);
  122. }
  123. }
  124. return null;
  125. }
  126. public function getRegion($str) {
  127. $province = [];
  128. $city = [];
  129. $area = [];
  130. foreach ($this->data as $v) {
  131. $item = $v;
  132. $strLen = strpos($str,$item['ProvinceShortName']);
  133. if($item['LevelType'] == 1 && $strLen !== false &&
  134. (empty($province) || $province['len'] > $strLen )
  135. ) {
  136. $v['len'] = $strLen;
  137. $province = $v;
  138. }
  139. }
  140. //城市列表
  141. if(!empty($province)) {
  142. $data = $this->getChild($province['ID']);
  143. if(count($data) == 1) {
  144. $data[0]['len'] = 0;
  145. $city = $data[0];
  146. } else {
  147. foreach ($data as $v) {
  148. $item = $v;
  149. $strLen = strpos($str,$item['CityShortName']);
  150. if($strLen !== false && (empty($city) || $city['len'] > $strLen ) && $province['ProvinceShortName']
  151. != $item['CityShortName'] && $v['LevelType'] == 2 ) {
  152. $v['len'] = $strLen;
  153. $city = $v;
  154. }
  155. }
  156. if(empty($city)) {
  157. foreach ($data as $v) {
  158. $item = $v;
  159. $strLen = strpos($str,$item['CityShortName']);
  160. if($strLen !== false && (empty($city) || $city['len'] > $strLen ) && $v['LevelType'] == 2 ) {
  161. $v['len'] = $strLen;
  162. $city = $v;
  163. }
  164. }
  165. }
  166. }
  167. }
  168. //地区数据
  169. if(!empty($city)) {
  170. $data = $this->getChild($city['ID']);
  171. foreach ($data as $v) {
  172. $item = $v;
  173. $strLen = strpos($str,$item['DistrictShortName']);
  174. if($strLen !== false) {
  175. $v['len'] = $strLen;
  176. $area = $v;
  177. }
  178. }
  179. }
  180. //地区
  181. foreach ($this->data as $v) {
  182. $item = $v;
  183. $strLen = strpos($str,$item['ProvinceShortName']);
  184. if($item['LevelType'] == 3 && $strLen !== false && empty($city) &&
  185. (empty($area) || $area['len'] < $strLen )
  186. ) {
  187. $v['len'] = $strLen;
  188. $area = $v;
  189. }
  190. }
  191. ////////////
  192. //省份
  193. if(!empty($province)) {
  194. $len = strpos($str,$province['Name']);
  195. $name = $province['ProvinceShortName'];
  196. if($len !== false && $len == $province['len']) {
  197. $name = $province['Name'];
  198. }
  199. $str = $this->strReplaceLimit($name,'',$str,1);
  200. }
  201. //城市列表
  202. if(!empty($city)) {
  203. $len = strpos($str,$city['Name']);
  204. $name = $city['CityShortName'];
  205. if($len !== false) {
  206. $name = $city['Name'];
  207. }
  208. $str = $this->strReplaceLimit($name,'',$str,1);
  209. }
  210. //城市列表
  211. if(!empty($area)) {
  212. $len = strpos($str,$area['Name']);
  213. $name = $area['DistrictShortName'];
  214. if($len !== false) {
  215. $name = $area['Name'];
  216. }
  217. $str = $this->strReplaceLimit($name,'',$str,1);
  218. }
  219. //var_dump(['address'=>trim($str),'province'=> empty($province) ? '' : $province['Name'],'city'=> empty($city) ? '' : $city['Name'],'area'=>empty($area) ? '' : $area['Name']]);
  220. return ['address'=>trim($str),'province'=> empty($province) ? '' : $province['Name'],'city'=> empty($city) ? '' : $city['Name'],'area'=>empty($area) ? '' : $area['Name']];
  221. }
  222. /**
  223. * 获取基础数据【缓存数据】
  224. */
  225. private function getData(){
  226. $data = cache('region');
  227. if(empty($data)){
  228. $data = Db::name("region")->field("ID,ParentId,LevelType,Name,Pinyin,ProvinceShortName,DistrictShortName,CityShortName")->select()->toArray();
  229. cache('region',$data);
  230. }
  231. return $data;
  232. }
  233. /**
  234. * @param $method
  235. * @param $args
  236. * @return mixed
  237. */
  238. public static function __callStatic($method, $args)
  239. {
  240. $model = new static();
  241. return call_user_func_array([$model, $method], $args);
  242. }
  243. /**
  244. $search:要替换的字符串或者数组
  245. $replace:要替换的值
  246. $subject:要替换的文本
  247. $limit:替换的此数字
  248. * @return string|string[]|null
  249. */
  250. function strReplaceLimit($search, $replace, $subject, $limit=-1) {
  251. if (is_array($search)) {
  252. foreach ($search as $k=>$v) {
  253. $search[$k] = '`' . preg_quote($search[$k],'`') . '`';
  254. }
  255. }
  256. else {
  257. $search = '`' . preg_quote($search,'`') . '`';
  258. }
  259. return preg_replace($search, $replace, $subject, $limit);
  260. }
  261. }