Region.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <?php
  2. namespace app\common\model;
  3. use think\Cache;
  4. use app\common\library\helper;
  5. /**
  6. * 地区模型
  7. * Class Region
  8. * @package app\common\model
  9. */
  10. class Region extends BaseModel
  11. {
  12. protected $name = 'region';
  13. protected $createTime = false;
  14. protected $updateTime = false;
  15. /**
  16. * 类型自动转换
  17. * @var array
  18. */
  19. protected $type = [
  20. 'id' => 'integer',
  21. 'pid' => 'integer',
  22. 'level' => 'integer',
  23. ];
  24. // 当前数据版本号
  25. private static $version = '1.2.5';
  26. // 县级市别名 (兼容微信端命名)
  27. private static $county = [
  28. '省直辖县级行政区划',
  29. '自治区直辖县级行政区划',
  30. ];
  31. /**
  32. * 根据id获取地区名称
  33. * @param $id
  34. * @return string
  35. */
  36. public static function getNameById($id)
  37. {
  38. return $id > 0 ? self::getCacheAll()[$id]['name'] : '其他';
  39. }
  40. /**
  41. * 根据名称获取地区id
  42. * @param $name
  43. * @param int $level
  44. * @param int $pid
  45. * @return mixed
  46. */
  47. public static function getIdByName($name, $level = 0, $pid = 0)
  48. {
  49. // 兼容:微信端"省直辖县级行政区划"
  50. if (in_array($name, static::$county)) {
  51. $name = '直辖县级';
  52. }
  53. $data = self::getCacheAll();
  54. foreach ($data as $item) {
  55. if ($item['name'] == $name && $item['level'] == $level && $item['pid'] == $pid)
  56. return $item['id'];
  57. }
  58. return 0;
  59. }
  60. /**
  61. * 获取所有地区(树状结构)
  62. * @return mixed
  63. */
  64. public static function getCacheTree()
  65. {
  66. return static::getCacheData('tree');
  67. }
  68. /**
  69. * 获取所有地区列表
  70. * @return mixed
  71. */
  72. public static function getCacheAll()
  73. {
  74. return static::getCacheData('all');
  75. }
  76. /**
  77. * 获取所有地区的总数
  78. * @return mixed
  79. */
  80. public static function getCacheCounts()
  81. {
  82. return static::getCacheData('counts');
  83. }
  84. /**
  85. * 获取缓存中的数据(存入静态变量)
  86. * @param null $item
  87. * @return array|mixed
  88. */
  89. private static function getCacheData($item = null)
  90. {
  91. static $cacheData = [];
  92. if (empty($cacheData)) {
  93. $static = new static;
  94. $cacheData = $static->regionCache();
  95. }
  96. if (is_null($item)) {
  97. return $cacheData;
  98. }
  99. return $cacheData[$item];
  100. }
  101. /**
  102. * 获取地区缓存
  103. * @return array|mixed
  104. * @throws \think\db\exception\DataNotFoundException
  105. * @throws \think\db\exception\ModelNotFoundException
  106. * @throws \think\exception\DbException
  107. */
  108. private function regionCache()
  109. {
  110. // 缓存的数据
  111. $complete = Cache::get('region');
  112. // 如果存在缓存则返回缓存的数据,否则从数据库中查询
  113. // 条件1: 获取缓存数据
  114. // 条件2: 数据版本号要与当前一致
  115. if (
  116. !empty($complete)
  117. && isset($complete['version'])
  118. && $complete['version'] == self::$version
  119. ) {
  120. return $complete;
  121. }
  122. // 所有地区
  123. $allList = $tempList = $this->getAllList();
  124. // 已完成的数据
  125. $complete = [
  126. 'all' => $allList,
  127. 'tree' => $this->getTreeList($allList),
  128. 'counts' => $this->getCount($allList),
  129. 'version' => self::$version,
  130. ];
  131. // 写入缓存
  132. Cache::tag('cache')->set('region', $complete);
  133. return $complete;
  134. }
  135. private static function getCount($allList)
  136. {
  137. $counts = [
  138. 'total' => count($allList),
  139. 'province' => 0,
  140. 'city' => 0,
  141. 'region' => 0,
  142. ];
  143. $level = [1 => 'province', 2 => 'city', 3 => 'region'];
  144. foreach ($allList as $item) {
  145. $counts[$level[$item['level']]]++;
  146. }
  147. return $counts;
  148. }
  149. /**
  150. * 格式化为树状格式
  151. * @param $allList
  152. * @return array
  153. */
  154. private function getTreeList($allList)
  155. {
  156. $treeList = [];
  157. foreach ($allList as $pKey => $province) {
  158. if ($province['level'] == 1) { // 省份
  159. $treeList[$province['id']] = $province;
  160. unset($allList[$pKey]);
  161. foreach ($allList as $cKey => $city) {
  162. if ($city['level'] == 2 && $city['pid'] == $province['id']) { // 城市
  163. $treeList[$province['id']]['city'][$city['id']] = $city;
  164. unset($allList[$cKey]);
  165. foreach ($allList as $rKey => $region) {
  166. if ($region['level'] == 3 && $region['pid'] == $city['id']) { // 地区
  167. $treeList[$province['id']]['city'][$city['id']]['region'][$region['id']] = $region;
  168. unset($allList[$rKey]);
  169. }
  170. }
  171. }
  172. }
  173. }
  174. }
  175. return $treeList;
  176. }
  177. /**
  178. * 从数据库中获取所有地区
  179. * @return array
  180. * @throws \think\db\exception\DataNotFoundException
  181. * @throws \think\db\exception\ModelNotFoundException
  182. * @throws \think\exception\DbException
  183. */
  184. private function getAllList()
  185. {
  186. $list = self::useGlobalScope(false)
  187. ->field('id, pid, name, level')
  188. ->select()
  189. ->toArray();
  190. return helper::arrayColumn2Key($list, 'id');
  191. }
  192. }