388 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
		
		
			
		
	
	
			388 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
|  | <?php | |||
|  | 
 | |||
|  | namespace app\model; | |||
|  | 
 | |||
|  | use Exception; | |||
|  | use think\Collection; | |||
|  | use think\db\exception\DataNotFoundException; | |||
|  | use think\db\exception\DbException; | |||
|  | use think\db\exception\ModelNotFoundException; | |||
|  | use think\Model; | |||
|  | use think\Paginator; | |||
|  | 
 | |||
|  | class Base extends Model | |||
|  | { | |||
|  |     protected $autoWriteTimestamp = false; | |||
|  | 
 | |||
|  |     // 布尔值数字关系
 | |||
|  |     public const BOOL_FALSE = 0; | |||
|  |     public const BOOL_TRUE  = 1; | |||
|  | 
 | |||
|  |     public const COMMON_ON  = 1; | |||
|  |     public const COMMON_OFF = 0; | |||
|  | 
 | |||
|  |     //根据Id列表获取列表
 | |||
|  |     public static function getListByIds($ids) | |||
|  |     { | |||
|  |         if (count($ids) == 0 || empty($ids)) { | |||
|  |             return []; | |||
|  |         } | |||
|  |         return self::where('id', 'in', $ids)->select()->toArray(); | |||
|  |     } | |||
|  | 
 | |||
|  |     //根据ID获取单条数据
 | |||
|  |     public static function getById($id) | |||
|  |     { | |||
|  |         if ($id <= 0) { | |||
|  |             return []; | |||
|  |         } | |||
|  |         return self::where('id', $id)->findOrEmpty()->toArray(); | |||
|  |     } | |||
|  | 
 | |||
|  |     /** | |||
|  |      * 通过ID查找记录 | |||
|  |      * | |||
|  |      * @param  int  $id | |||
|  |      * @param  array  $fields | |||
|  |      * @param  callable|null  $call | |||
|  |      * @return array|Model|null | |||
|  |      * @throws DataNotFoundException | |||
|  |      * @throws DbException | |||
|  |      * @throws ModelNotFoundException | |||
|  |      */ | |||
|  |     public static function findById(int $id, array $fields = [], callable $call = null) | |||
|  |     { | |||
|  |         $q = self::when(!empty($fields), function ($q) use ($fields) { | |||
|  |             $q->field($fields); | |||
|  |         }); | |||
|  |         if ($call !== null) { | |||
|  |             $q = $call($q); | |||
|  |         } | |||
|  |         return $q->find($id); | |||
|  |     } | |||
|  | 
 | |||
|  |     /** | |||
|  |      * 查找单个记录 | |||
|  |      * | |||
|  |      * @param  array  $where | |||
|  |      * @param  array  $fields | |||
|  |      * @param  callable|null  $call | |||
|  |      * @return array|Model|null | |||
|  |      * @throws DataNotFoundException | |||
|  |      * @throws DbException | |||
|  |      * @throws ModelNotFoundException | |||
|  |      */ | |||
|  |     public static function findOne(array $where = [], array $fields = [], callable $call = null) | |||
|  |     { | |||
|  |         $q = self::when(!empty($fields), function ($q) use ($fields) { | |||
|  |             $q->field($fields); | |||
|  |         })->where($where); | |||
|  | 
 | |||
|  |         if ($call !== null) { | |||
|  |             $q = $call($q); | |||
|  |         } | |||
|  |         return $q->find(); | |||
|  |     } | |||
|  | 
 | |||
|  |     //根据ID更新数据
 | |||
|  |     public static function updateById($id, $data) | |||
|  |     { | |||
|  |         return self::where('id', $id)->update($data); | |||
|  |     } | |||
|  | 
 | |||
|  |     //根据where条件和排序获取记录
 | |||
|  |     public static function getListByWhereAndOrder($where, $order, $limit = 1) | |||
|  |     { | |||
|  |         return self::where($where) | |||
|  |             ->order($order) | |||
|  |             ->limit($limit) | |||
|  |             ->select() | |||
|  |             ->toArray(); | |||
|  |     } | |||
|  | 
 | |||
|  |     /** | |||
|  |      * 根据ID删除数据 | |||
|  |      * | |||
|  |      * @param  int  $id | |||
|  |      * @return bool | |||
|  |      */ | |||
|  |     public static function deleteById(int $id): bool | |||
|  |     { | |||
|  |         return self::where('id', $id)->delete(); | |||
|  |     } | |||
|  | 
 | |||
|  |     /** | |||
|  |      * 根据ID列表删除数据 | |||
|  |      * | |||
|  |      * @param  array  $ids | |||
|  |      * @return bool | |||
|  |      */ | |||
|  |     public static function deleteByIds(array $ids): bool | |||
|  |     { | |||
|  |         return self::whereIn('id', $ids)->delete(); | |||
|  |     } | |||
|  | 
 | |||
|  |     /** | |||
|  |      * 排序 | |||
|  |      * | |||
|  |      * @param  int  $id  调整ID | |||
|  |      * @param  string  $type  本次操作类型 向上、向下 | |||
|  |      * @param  int  $num  移动位数 | |||
|  |      * @param  string  $listType  列表的排序方式 默认为降序 | |||
|  |      * @param  array  $where  额外条件 如限制在指定分类下 where[] = ['category_id', '=', 6] | |||
|  |      * @return array | |||
|  |      * @throws Exception | |||
|  |      */ | |||
|  |     public static function sort(int $id, string $type, int $num = 1, string $listType = 'desc', array $where = []): array | |||
|  |     { | |||
|  |         $res  = ['code' => 0, 'msg' => 'success']; | |||
|  |         $item = self::getById($id); | |||
|  | 
 | |||
|  |         if (!$item) { | |||
|  |             $res['code'] = 1; | |||
|  |             $res['msg']  = '记录不存在'; | |||
|  |             return $res; | |||
|  |         } | |||
|  | 
 | |||
|  |         if ($listType == 'desc') { | |||
|  |             if ($type == 'down') { | |||
|  |                 $where[] = ['sort', '<', $item['sort']]; | |||
|  |                 $order   = "sort desc"; | |||
|  |             } else { | |||
|  |                 $where[] = ['sort', '>', $item['sort']]; | |||
|  |                 $order   = "sort asc"; | |||
|  |             } | |||
|  |         } else { | |||
|  |             if ($type == 'up') { | |||
|  |                 $where[] = ['sort', '<', $item['sort']]; | |||
|  |                 $order   = "sort desc"; | |||
|  |             } else { | |||
|  |                 $where[] = ['sort', '>', $item['sort']]; | |||
|  |                 $order   = "sort asc"; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         $forSortItems = self::getListByWhereAndOrder($where, $order, $num); | |||
|  |         if (!empty($forSortItems)) { | |||
|  |             $updateData   = []; | |||
|  |             $forSortCount = count($forSortItems); | |||
|  |             for ($i = 0; $i < $forSortCount; $i++) { | |||
|  |                 if ($i == 0) { | |||
|  |                     $updateData[] = [ | |||
|  |                         'id'   => $forSortItems[$i]['id'], | |||
|  |                         'sort' => $item['sort'] | |||
|  |                     ]; | |||
|  |                 } else { | |||
|  |                     $updateData[] = [ | |||
|  |                         'id'   => $forSortItems[$i]['id'], | |||
|  |                         'sort' => $forSortItems[$i - 1]['sort'] | |||
|  |                     ]; | |||
|  |                 } | |||
|  |             } | |||
|  |             $updateData[] = [ | |||
|  |                 'id'   => $item['id'], | |||
|  |                 'sort' => $forSortItems[$i - 1]['sort'] | |||
|  |             ]; | |||
|  | 
 | |||
|  |             if (!empty($updateData)) { | |||
|  |                 $obj = new static(); | |||
|  |                 $obj->saveAll($updateData); | |||
|  |                 return $res; | |||
|  |             } | |||
|  |         } | |||
|  |         $res['code'] = 1; | |||
|  |         $res['msg']  = '无需调整'; | |||
|  |         return $res; | |||
|  |     } | |||
|  | 
 | |||
|  |     /** | |||
|  |      * 查询列表 [带分页 适用于后台] | |||
|  |      * | |||
|  |      * @param  array  $data  查询数据 格式如下 | |||
|  |      * [ | |||
|  |      *   'fields' => ['id','title','desc'],//查询字段
 | |||
|  |      *   'where'  => [ | |||
|  |      *                  ['name', 'like', '%thinkphp%'], | |||
|  |      *                  ['title', 'like', '%thinkphp%'], | |||
|  |      *                  ['id', '>', 0], | |||
|  |      *                  ['status', '=', 1], | |||
|  |      *               ],//查询条件
 | |||
|  |      *   'order'  => ['order'=>'desc','id'=>'desc'],//排序
 | |||
|  |      *   'size' => 50,//每页数量
 | |||
|  |      * ] | |||
|  |      * @param  array  $pageParams  分页参数 具体参考:https://www.kancloud.cn/manual/thinkphp6_0/1037638 | |||
|  |      * @param  callable|null  $callback  复杂查询条件 使用闭包查询 此时建议data留空 | |||
|  |      * @return Paginator | |||
|  |      * @throws DbException | |||
|  |      */ | |||
|  |     public static function findListWithPaginate(array $data = [], array $pageParams = [], callable $callback = null): Paginator | |||
|  |     { | |||
|  |         $q      = new static(); | |||
|  |         $fields = isset($data['fields']) && !empty($data['fields']) ? $data['fields'] : []; | |||
|  |         $where  = isset($data['where']) && !empty($data['where']) ? $data['where'] : []; | |||
|  |         $order  = isset($data['order']) && !empty($data['order']) ? $data['order'] : []; | |||
|  |         $limit  = $data['size'] ?? 20; | |||
|  | 
 | |||
|  |         if (count($where)) { | |||
|  |             $q = $q->where($where); | |||
|  |         } | |||
|  | 
 | |||
|  |         if (count($fields)) { | |||
|  |             $q = $q->field($fields); | |||
|  |         } | |||
|  | 
 | |||
|  |         if ($callback) { | |||
|  |             $q = $callback($q); | |||
|  |         } | |||
|  | 
 | |||
|  |         if (count($order)) { | |||
|  |             $q = $q->order($order); | |||
|  |         } | |||
|  | 
 | |||
|  |         $pageParams['list_rows'] = $limit; | |||
|  | 
 | |||
|  |         return $q->paginate($pageParams); | |||
|  |     } | |||
|  | 
 | |||
|  |     /** | |||
|  |      * 查询列表 | |||
|  |      * | |||
|  |      * @param  array  $simpleWhere  简易查询条件 | |||
|  |      * @param  array  $fields  查询字段 []表示全部 | |||
|  |      * @param  int  $page  默认第一页 0不限制 | |||
|  |      * @param  int  $limit  限制条数 0不限制 | |||
|  |      * @param  callable|null  $callback  复杂的条件 使用闭包查询 | |||
|  |      * @param  array  $orders 键值对,排序 | |||
|  |      * @return array | |||
|  |      * @throws Exception | |||
|  |      */ | |||
|  |     public static function findList(array $simpleWhere = [], array $fields = [], int $page = 1, int $limit = 0, callable $callback = null, array $orders = []): array | |||
|  |     { | |||
|  |         $q    = new static(); | |||
|  |         $data = [ | |||
|  |             'total'   => 0, | |||
|  |             'current' => $page, | |||
|  |             'size'    => $limit, | |||
|  |             'list'    => new Collection(), | |||
|  |         ]; | |||
|  | 
 | |||
|  |         if (count($fields)) { | |||
|  |             $q = $q->field($fields); | |||
|  |         } | |||
|  | 
 | |||
|  |         if (count($simpleWhere)) { | |||
|  |             $q = $q->where($simpleWhere); | |||
|  |         } | |||
|  | 
 | |||
|  |         if ($callback) { | |||
|  |             $q = $callback($q); | |||
|  |         } | |||
|  | 
 | |||
|  |         $data['total'] = $q->count(); | |||
|  | 
 | |||
|  |         if ($data['total']) { | |||
|  |             if (count($orders)) { | |||
|  |                 $q = $q->order($orders); | |||
|  |             } | |||
|  |             if ($limit) { | |||
|  |                 if ($page) { | |||
|  |                     $q = $q->page($page); | |||
|  |                 } | |||
|  |                 $q = $q->limit($limit); | |||
|  |             } | |||
|  | 
 | |||
|  |             $data['list'] = $q->select(); | |||
|  |         } | |||
|  | 
 | |||
|  |         return $data; | |||
|  |     } | |||
|  | 
 | |||
|  |     /** | |||
|  |      * 获取路径 | |||
|  |      * | |||
|  |      * @param  int  $pid | |||
|  |      * @return string | |||
|  |      * @throws DataNotFoundException | |||
|  |      * @throws DbException | |||
|  |      * @throws ModelNotFoundException | |||
|  |      */ | |||
|  |     public static function getPath(int $pid): string | |||
|  |     { | |||
|  |         if ($pid == 0) { | |||
|  |             $path = ',0,'; | |||
|  |         } else { | |||
|  |             $parent = self::findById($pid); | |||
|  |             if (empty($parent)) { | |||
|  |                 $path = ',0,'; | |||
|  |             } else { | |||
|  |                 $path = $parent['path'].$parent['id'].','; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         return $path; | |||
|  |     } | |||
|  | 
 | |||
|  |     /** | |||
|  |      * 刷新路径 | |||
|  |      * | |||
|  |      * @param  int  $pid | |||
|  |      * @param  array  $data  默认全部 若data不为空 至少包含[id,path, $pidField] | |||
|  |      * @param  string  $pidField  父级ID字段名 默认 pid | |||
|  |      * @throws Exception | |||
|  |      */ | |||
|  |     public static function refreshPath(int $pid = 0, array $data = [], string $pidField = 'pid') | |||
|  |     { | |||
|  |         $data           = !empty($data) ? $data : self::column('id,path,'.$pidField); | |||
|  |         $updateAllPaths = []; | |||
|  |         self::recursionPath($pid, $data, $updateAllPaths); | |||
|  | 
 | |||
|  |         (new static())->saveAll($updateAllPaths); | |||
|  |     } | |||
|  | 
 | |||
|  |     /** | |||
|  |      * 获取递归最新路径 | |||
|  |      * | |||
|  |      * @param  int  $pid | |||
|  |      * @param  array  $data  全部数据 尽量传全部数据 | |||
|  |      * @param  array  $paths | |||
|  |      */ | |||
|  |     public static function recursionPath(int $pid, array $data, array &$paths = []) | |||
|  |     { | |||
|  |         foreach ($data as $k => $v) { | |||
|  |             if ($pid == $v['pid']) { | |||
|  |                 $arr       = []; | |||
|  |                 $arr['id'] = $v['id']; | |||
|  |                 if ($pid == 0) { | |||
|  |                     $arr['path'] = ',0,'; | |||
|  |                 } else { | |||
|  |                     $arr['path'] = $paths[$v['pid']]['path'].$v['pid'].','; | |||
|  |                 } | |||
|  |                 $paths[$v['id']] = $arr; | |||
|  | 
 | |||
|  |                 unset($data[$k]); | |||
|  | 
 | |||
|  |                 self::recursionPath($v['id'], $data, $paths); | |||
|  |             } | |||
|  |         } | |||
|  |     } | |||
|  | 
 | |||
|  |     /** | |||
|  |      * 获取所有后代ID[包含孙级]  仅对拥有path字段的表生效 | |||
|  |      * | |||
|  |      * @param  int  $id | |||
|  |      * @return array | |||
|  |      * @throws DataNotFoundException | |||
|  |      * @throws DbException | |||
|  |      * @throws ModelNotFoundException | |||
|  |      */ | |||
|  |     public static function getAllChildrenIds(int $id): array | |||
|  |     { | |||
|  |         $item = self::find($id); | |||
|  |         if ($item && isset($item['path'])) { | |||
|  |             $path = $item['path'].$id.','; | |||
|  |             return self::where('path', 'like', $path.'%')->column('id'); | |||
|  |         } else { | |||
|  |             return []; | |||
|  |         } | |||
|  |     } | |||
|  | } |