ApiService.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkCMF [ WE CAN DO IT MORE SIMPLE ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: 老猫 <thinkcmf@126.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\portal\service;
  12. use app\portal\model\PortalPostModel;
  13. use app\portal\model\PortalCategoryModel;
  14. use think\db\Query;
  15. use app\portal\model\PortalTagModel;
  16. class ApiService
  17. {
  18. /**
  19. * 功能:查询文章列表,支持分页;<br>
  20. * 注:此方法查询时关联两个表portal_category_post(category_post),portal_post(post);在指定排序(order),指定查询条件(where)最好指定一下表别名
  21. * @param array $param 查询参数<pre>
  22. * array(
  23. * 'category_ids'=>'',
  24. * 'where'=>'',
  25. * 'limit'=>'',
  26. * 'order'=>'',
  27. * 'page'=>'',
  28. * 'relation'=>''
  29. * )
  30. * 字段说明:
  31. * category_ids:文章所在分类,可指定一个或多个分类id,以英文逗号分隔,如1或1,2,3 默认值为全部
  32. * field:调用指定的字段@return array 包括分页的文章列表<pre>
  33. * 格式:
  34. * array(
  35. * "articles"=>array(),//文章列表,array
  36. * "page"=>"",//生成的分页html,不分页则没有此项
  37. * "total"=>100, //符合条件的文章总数,不分页则没有此项
  38. * "total_pages"=>5 // 总页数,不分页则没有此项
  39. * )</pre>
  40. * @todo
  41. * 如只调用posts表里的id和post_title字段可以是post.id,post.post_title; 默认全部,
  42. * 此方法查询时关联两个表portal_category_post(category_post),portal_post(post);
  43. * 所以最好指定一下表名,以防字段冲突
  44. * limit:数据条数,默认值为10,可以指定从第几条开始,如3,8(表示共调用8条,从第3条开始)
  45. * order:排序方式,如按posts表里的published_time字段倒序排列:post.published_time desc
  46. * where:查询条件,字符串形式,和sql语句一样,请在事先做好安全过滤,最好使用第二个参数$where的数组形式进行过滤,此方法查询时关联多个表,所以最好指定一下表名,以防字段冲突,查询条件(只支持数组),格式和thinkPHP的where方法一样,此方法查询时关联多个表,所以最好指定一下表名,以防字段冲突;
  47. * </pre>
  48. */
  49. public static function articles($param)
  50. {
  51. $portalPostModel = new PortalPostModel();
  52. $where = [
  53. 'post.post_status' => 1,
  54. 'post.post_type' => 1,
  55. 'post.delete_time' => 0
  56. ];
  57. $wherePublishedTime = function (Query $query) {
  58. $query->where('post.published_time', '>', 0)
  59. ->where('post.published_time', '<', time());
  60. };
  61. $paramWhere = empty($param['where']) ? '' : $param['where'];
  62. $limit = empty($param['limit']) ? 10 : $param['limit'];
  63. $order = empty($param['order']) ? '' : $param['order'];
  64. $page = isset($param['page']) ? $param['page'] : false;
  65. $relation = empty($param['relation']) ? '' : $param['relation'];
  66. $categoryIds = empty($param['category_ids']) ? '' : $param['category_ids'];
  67. $whereCategoryId = null;
  68. if (!empty($categoryIds)) {
  69. $field = !empty($param['field']) ? $param['field'] : 'post.*,min(category_post.category_id) as category_id';
  70. if (!is_array($categoryIds)) {
  71. $categoryIds = explode(',', $categoryIds);
  72. }
  73. if (count($categoryIds) == 1) {
  74. $whereCategoryId = function (Query $query) use ($categoryIds) {
  75. $query->where('category_post.category_id', $categoryIds[0]);
  76. };
  77. } else {
  78. $whereCategoryId = function (Query $query) use ($categoryIds) {
  79. $query->where('category_post.category_id', 'in', $categoryIds);
  80. };
  81. }
  82. } else {
  83. $field = !empty($param['field']) ? $param['field'] : 'post.*,min(category_post.category_id) as category_id';
  84. }
  85. $articles = $portalPostModel->alias('post')->field($field)
  86. ->join('portal_category_post category_post', 'post.id = category_post.post_id')
  87. ->where($where)
  88. ->where($paramWhere)
  89. ->where($whereCategoryId)
  90. ->where($wherePublishedTime)
  91. ->order($order)
  92. ->group('post.id');
  93. $return = [];
  94. if (empty($page)) {
  95. $length = null;
  96. if (strpos($limit, ',')) {
  97. list($offset, $length) = explode(',', $limit);
  98. } else {
  99. $offset = $limit;
  100. }
  101. $articles = $articles->limit($offset, $length)->select();
  102. if (!empty($relation) && !empty($articles['items'])) {
  103. $articles->load($relation);
  104. }
  105. $return['articles'] = $articles;
  106. } else {
  107. if (is_array($page)) {
  108. if (empty($page['list_rows'])) {
  109. $page['list_rows'] = 10;
  110. }
  111. $articles = $articles->paginate($page);
  112. } else {
  113. $articles = $articles->paginate(intval($page));
  114. }
  115. if (!empty($relation) && !empty($articles['items'])) {
  116. $articles->load($relation);
  117. }
  118. $articles->appends(request()->get());
  119. $articles->appends(request()->post());
  120. $return['articles'] = $articles->items();
  121. $return['page'] = $articles->render();
  122. $return['total'] = $articles->total();
  123. $return['total_pages'] = $articles->lastPage();
  124. }
  125. return $return;
  126. }
  127. /**
  128. * 功能:查询标签文章列表,支持分页;<br>
  129. * 注:此方法查询时关联两个表portal_tag_post(tag_post),portal_post(post);在指定排序(order),指定查询条件(where)最好指定一下表别名
  130. * @param array $param 查询参数<pre>
  131. * array(
  132. * 'tag_id'=>'',
  133. * 'where'=>'',
  134. * 'limit'=>'',
  135. * 'order'=>'',
  136. * 'page'=>'',
  137. * 'relation'=>''
  138. * )
  139. * 字段说明:
  140. * field:调用指定的字段@return array 包括分页的文章列表<pre>
  141. * 格式:
  142. * array(
  143. * "articles"=>array(),//文章列表,array
  144. * "page"=>"",//生成的分页html,不分页则没有此项
  145. * "total"=>100, //符合条件的文章总数,不分页则没有此项
  146. * "total_pages"=>5 // 总页数,不分页则没有此项
  147. * )</pre>
  148. * @todo
  149. * 如只调用posts表里的id和post_title字段可以是post.id,post.post_title; 默认全部,
  150. * 此方法查询时关联两个表portal_tag_post(category_post),portal_post(post);
  151. * 所以最好指定一下表名,以防字段冲突
  152. * limit:数据条数,默认值为10,可以指定从第几条开始,如3,8(表示共调用8条,从第3条开始)
  153. * order:排序方式,如按posts表里的published_time字段倒序排列:post.published_time desc
  154. * where:查询条件,字符串形式,和sql语句一样,请在事先做好安全过滤,最好使用第二个参数$where的数组形式进行过滤,此方法查询时关联多个表,所以最好指定一下表名,以防字段冲突,查询条件(只支持数组),格式和thinkPHP的where方法一样,此方法查询时关联多个表,所以最好指定一下表名,以防字段冲突;
  155. * </pre>
  156. */
  157. public static function tagArticles($param)
  158. {
  159. $portalPostModel = new PortalPostModel();
  160. $where = [
  161. ['post.post_status' ,'=', 1],
  162. ['post.post_type' ,'=', 1],
  163. ['post.delete_time' ,'=', 0]
  164. ];
  165. $paramWhere = empty($param['where']) ? '' : $param['where'];
  166. $limit = empty($param['limit']) ? 10 : $param['limit'];
  167. $order = empty($param['order']) ? '' : $param['order'];
  168. $page = isset($param['page']) ? $param['page'] : false;
  169. $relation = empty($param['relation']) ? '' : $param['relation'];
  170. $tagId = empty($param['tag_id']) ? '' : $param['tag_id'];
  171. $articles = $portalPostModel->alias('post');
  172. if (empty($tagId)) {
  173. return null;
  174. } else {
  175. $field = !empty($param['field']) ? $param['field'] : 'post.*';
  176. $articles = $articles->join('portal_tag_post tag_post', 'post.id = tag_post.post_id');
  177. $where[] = ['tag_post.tag_id', '=', $tagId];
  178. }
  179. $wherePublishedTime = function (Query $query) {
  180. $query->where('post.published_time', '>', 0)
  181. ->where('post.published_time', '<', time());
  182. };
  183. $articles = $articles->field($field)
  184. ->where($where)
  185. ->where($paramWhere)
  186. ->where($wherePublishedTime)
  187. ->order($order);
  188. $return = [];
  189. if (empty($page)) {
  190. $articles = $articles->limit($limit)->select();
  191. if (!empty($relation) && !empty($articles['items'])) {
  192. $articles->load($relation);
  193. }
  194. $return['articles'] = $articles;
  195. } else {
  196. if (is_array($page)) {
  197. if (empty($page['list_rows'])) {
  198. $page['list_rows'] = 10;
  199. }
  200. $articles = $articles->paginate($page);
  201. } else {
  202. $articles = $articles->paginate(intval($page));
  203. }
  204. if (!empty($relation) && !empty($articles->items())) {
  205. $articles->load($relation);
  206. }
  207. $articles->appends(request()->get());
  208. $articles->appends(request()->post());
  209. $return['articles'] = $articles->items();
  210. $return['page'] = $articles->render();
  211. $return['total'] = $articles->total();
  212. $return['total_pages'] = $articles->lastPage();
  213. }
  214. return $return;
  215. }
  216. /**
  217. * 获取指定id的文章
  218. * @param int $id
  219. * @return array|false|\PDOStatement|string|\think\Model
  220. */
  221. public static function article($id)
  222. {
  223. $portalPostModel = new PortalPostModel();
  224. $where = [
  225. 'post_status' => 1,
  226. 'post_type' => 1,
  227. 'id' => $id,
  228. 'delete_time' => 0
  229. ];
  230. $wherePublishedTime = function (Query $query) {
  231. $query->where('published_time', '>', 0)
  232. ->where('published_time', '<', time());
  233. };
  234. return $portalPostModel->where($where)
  235. ->where($wherePublishedTime)
  236. ->find();
  237. }
  238. /**
  239. * 获取指定条件的页面列表
  240. * @param array $param 查询参数<pre>
  241. * array(
  242. * 'where'=>'',
  243. * 'order'=>'',
  244. * )</pre>
  245. * @return false|\PDOStatement|string|\think\Collection
  246. */
  247. public static function pages($param)
  248. {
  249. $paramWhere = empty($param['where']) ? '' : $param['where'];
  250. $order = empty($param['order']) ? '' : $param['order'];
  251. $portalPostModel = new PortalPostModel();
  252. $where = [
  253. 'post_status' => 1,
  254. 'post_type' => 2, //页面
  255. 'delete_time' => 0
  256. ];
  257. $wherePublishedTime = function (Query $query) {
  258. $query->where('published_time', '>', 0)
  259. ->where('published_time', '<', time());
  260. };
  261. return $portalPostModel
  262. ->where($where)
  263. ->where($paramWhere)
  264. ->where($wherePublishedTime)
  265. ->order($order)
  266. ->select();
  267. }
  268. /**
  269. * 获取指定id的页面
  270. * @param int $id 页面的id
  271. * @return array|false|\PDOStatement|string|\think\Model 返回符合条件的页面
  272. */
  273. public static function page($id)
  274. {
  275. $portalPostModel = new PortalPostModel();
  276. $where = [
  277. 'post_status' => 1,
  278. 'post_type' => 2,
  279. 'id' => $id,
  280. 'delete_time' => 0
  281. ];
  282. $wherePublishedTime = function (Query $query) {
  283. $query->where('published_time', '>', 0)
  284. ->where('published_time', '<', time());
  285. };
  286. return $portalPostModel->where($where)
  287. ->where($wherePublishedTime)
  288. ->find();
  289. }
  290. /**
  291. * 返回指定分类
  292. * @param int $id 分类id
  293. * @return array 返回符合条件的分类
  294. */
  295. public static function category($id)
  296. {
  297. $portalCategoryModel = new PortalCategoryModel();
  298. $where = [
  299. 'status' => 1,
  300. 'delete_time' => 0,
  301. 'id' => $id
  302. ];
  303. return $portalCategoryModel->where($where)->find();
  304. }
  305. /**
  306. * 返回指定分类下的子分类
  307. * @param int $categoryId 分类id
  308. * @param $field string 指定查询字段
  309. * @return false|\PDOStatement|string|\think\Collection 返回指定分类下的子分类
  310. * @throws \think\db\exception\ModelNotFoundException
  311. * @throws \think\exception\DbException
  312. * @throws \think\db\exception\DataNotFoundException
  313. */
  314. public static function subCategories($categoryId, $field = '*')
  315. {
  316. $portalCategoryModel = new PortalCategoryModel();
  317. $where = [
  318. 'status' => 1,
  319. 'delete_time' => 0,
  320. 'parent_id' => $categoryId
  321. ];
  322. return $portalCategoryModel->field($field)->where($where)->order('list_order ASC')->select();
  323. }
  324. /**
  325. * 返回指定分类下的所有子分类
  326. * @param int $categoryId 分类id
  327. * @return array 返回指定分类下的所有子分类
  328. */
  329. public static function allSubCategories($categoryId)
  330. {
  331. $portalCategoryModel = new PortalCategoryModel();
  332. $categoryId = intval($categoryId);
  333. if ($categoryId !== 0) {
  334. $category = $portalCategoryModel->field('path')->where('id', $categoryId)->find();
  335. if (empty($category)) {
  336. return [];
  337. }
  338. $categoryPath = $category['path'];
  339. } else {
  340. $categoryPath = 0;
  341. }
  342. $where = [
  343. 'status' => 1,
  344. 'delete_time' => 0
  345. ];
  346. return $portalCategoryModel->where($where)->whereLike('path', "$categoryPath-%")->select();
  347. }
  348. /**
  349. * 返回符合条件的所有分类
  350. * @param array $param 查询参数<pre>
  351. * array(
  352. * 'where'=>'',
  353. * 'order'=>'',
  354. * )</pre>
  355. * @return false|\PDOStatement|string|\think\Collection
  356. */
  357. public static function categories($param)
  358. {
  359. $paramWhere = empty($param['where']) ? '' : $param['where'];
  360. $order = empty($param['order']) ? '' : $param['order'];
  361. $portalCategoryModel = new PortalCategoryModel();
  362. $where = [
  363. 'status' => 1,
  364. 'delete_time' => 0,
  365. ];
  366. $temp = $portalCategoryModel
  367. ->where($where)
  368. ->where($paramWhere)
  369. ->order($order);
  370. if (!empty($param['ids'])) {
  371. $temp->whereIn('id', $param['ids']);
  372. }
  373. return $temp->select();
  374. }
  375. /**
  376. * 获取面包屑数据
  377. * @param int $categoryId 当前文章所在分类,或者当前分类的id
  378. * @param boolean $withCurrent 是否获取当前分类
  379. * @return array 面包屑数据
  380. */
  381. public static function breadcrumb($categoryId, $withCurrent = false)
  382. {
  383. $data = [];
  384. $portalCategoryModel = new PortalCategoryModel();
  385. $path = $portalCategoryModel->where(['id' => $categoryId])->value('path');
  386. if (!empty($path)) {
  387. $parents = explode('-', $path);
  388. if (!$withCurrent) {
  389. array_pop($parents);
  390. }
  391. if (!empty($parents)) {
  392. $data = $portalCategoryModel->where('id', 'in', $parents)->order('path ASC')->select();
  393. }
  394. }
  395. return $data;
  396. }
  397. /**
  398. * 返回指定文章的标签
  399. * @param int $id 文章ID
  400. * @return array 返回符合条件的所有标签
  401. */
  402. public static function tags($id)
  403. {
  404. $portalTagModel = new PortalTagModel();
  405. $where = [
  406. 'tags.status' => 1,
  407. 'tag_post.post_id' => $id
  408. ];
  409. return $portalTagModel->alias('tags')
  410. ->where($where)
  411. ->join('portal_tag_post tag_post', 'tags.id = tag_post.tag_id')
  412. ->select();
  413. }
  414. }