有时候我们希望能和前端好好对接一个页面的功能性展示,如支持的搜索条件有哪些,支持的字段有哪些,复杂搜索
组件代码 ComplexSearch.php
<?php
/**
* Notes:描述该文件的用途
* History:文件历史
* tanyong 2022/5/18
*/
namespace App\components\ComplexSearch;
use App\components\ComplexSearch\Exceptions\ComplexException;
use App\components\ComplexSearch\Exceptions\Ecode;
use App\Models\User;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Arr;
abstract class ComplexSearch
{
/**
* @var null 关联的模型表
*/
public $eloquentModelTable = null;
/**
* @var \Illuminate\Database\Eloquent\Builder
*/
public $eloquentQuery = null;
/**
* @var array 列表标题
*/
public $headers = [];
/**
* @var array 需要隐藏的字段
*/
protected $hidden = [];
/**
* @var array 索引条件
*/
public $whereConditions = [];
/**
* @var array 支持的索引条件
*/
public $conditions = [];
/**
* @var string[] 要查询的字段
*/
public $selectFields = ['*'];
/**
* @var int 目标页数
*/
public $page = 1;
/**
* @var int 每页显示行数
*/
public $pageSize = 25;
/**
* @var array 排序
*/
public $orderBy = [
'field' => 'created_at',
'type' => 'desc'
];
public function __construct()
{
//启动组件检查
$this->startCheck();
}
/**
* Notes:构建搜索条件
* Author:tanyong
* DateTime:2022/5/18
* @param array $params
*/
public function make($params)
{
//获取需要查询的字段
if (isset($params['fields'])) {
$this->selectFields = $params['fields'];
}
//分页数
if (isset($params['page']) && $params['page'] >= 1) {
$this->page = $params['page'];
}
//每页显示记录条数
if (isset($params['pageSize']) && $params['pageSize'] >= 1) {
$this->pageSize = $params['pageSize'];
}
//索引条件
if (isset($params['params']) && !empty($params['params'])) {
$keys = array_column($params['params'],0);
$condtionKeys = array_keys($this->conditions);
foreach ($keys as $key) {
if(!in_array($key,$condtionKeys))
throw new ComplexException('未知的检索条件:'.$key,Ecode::PARAMS_ERROR);
}
$this->whereConditions = $params['params'];
}
return $this;
}
public function query()
{
$query = $this->getEloquentQuery();
//条件组合
if (!empty($this->whereConditions)) {
foreach ($this->whereConditions as $condtion) {
$key = $condtion[0];
$type = $condtion[1];
$value = $condtion[2];
if(!is_string($key))
throw new ComplexException('键名不是字符串',Ecode::PARAMS_ERROR);
//开始条件组合
switch ($type) {
case 'eq':
if(!is_string($value))
throw new ComplexException('对应值不是字符串',Ecode::PARAMS_ERROR);
$query->where($key, $value);
break;
case 'select':
if(!is_string($value))
throw new ComplexException('对应值不是字符串',Ecode::PARAMS_ERROR);
$query->where($key, $value);
break;
case 'section':
if(!is_array($value))
throw new ComplexException('对应值不是数组',Ecode::PARAMS_ERROR);
$query->where([
[$key, '>=', $value[0]],
[$key, '<=', $value[1]]
]);
break;
case 'not_eq':
if(!is_string($value))
throw new ComplexException('对应值不是字符串',Ecode::PARAMS_ERROR);
$query->where($key, '!=', $value);
break;
default:
$query->where($key, $value);
}
}
}
//排序
$query->orderBy($this->orderBy['field'], $this->orderBy['type']);
return $this;
}
public function get()
{
$result = [];
$this->query();
$query = $this->getEloquentQuery();
//字段效验
$selectFields = $this->checkFields($this->selectFields);
$pageInfo = $query->paginate($this->pageSize, $selectFields, 'page', $this->page);
//隐藏目标字段
if(!empty($pageInfo->items()) && !empty($this->hidden))
{
$list = $this->hiddenFields($pageInfo->items());
}
$result['pageInfo'] = [
'current_page' => $pageInfo->currentPage(),
'first_page_url' => $pageInfo->previousPageUrl(),
'next_page_url' => $pageInfo->nextPageUrl(),
'last_page' => $pageInfo->lastPage(),
'list' => $list
];
$result['conditions'] = $this->conditions;
$result['headers'] = $this->headers;
return $result;
}
public function checkFields($fields)
{
if($fields[0] != '*' && !empty($fields))
{
$headerKeys = array_keys($this->headers);
foreach($headerKeys as $key)
{
if(!in_array($key,$fields))
{
array_push($fields,$key);
}
}
}
return $fields;
}
/**
* @param User [] $data
*/
public function hiddenFields($data)
{
if(!empty($this->hidden) && !empty($data))
{
$removeStatus = false;
$keyColumns = array_keys($data[0]->getOriginal());
foreach($this->hidden as $field)
{
if(in_array($field,$keyColumns))
{
$removeStatus = true;
break;
}
}
if($removeStatus)
{
$data = array_map(function($item){
foreach($this->hidden as $field)
if(isset($item[$field]))
unset($item[$field]);
return $item;
},$data);
}
}
return $data;
}
public function getEloquentModelTable()
{
if (empty($this->eloquentModelTable))
throw new ComplexException('没有指定关联的表', Ecode::ERROR_TABLE);
return $this->eloquentModelTable;
}
/**
* @return null
*/
public function getEloquentQuery()
{
if (empty($this->eloquentQuery)) {
$class = $this->getEloquentModelTable();
$this->eloquentQuery = $class::query();
}
return $this->eloquentQuery;
}
public function startCheck()
{
//效验支持的条件
if(empty($this->conditions))
throw new ComplexException('支持的查询条件不可为空',Ecode::IS_EMPTY_CONDITION);
//效验需要隐藏的字段是否和headers标题头冲突
if(!empty($this->hidden))
{
$headerKeys = array_column($this->headers,'value');
$intersection = array_intersect($headerKeys,$this->hidden);
if(!empty($intersection))
throw new ComplexException('headers表头信息和需要隐藏字段不能存在交集',Ecode::PARAMS_ERROR);
}
}
}
继承类实现
<?php
/**
* Notes:描述该文件的用途
* History:文件历史
* tanyong 2022/5/18
*/
namespace App\Services\User\Search;
use App\components\ComplexSearch\ComplexSearch;
use App\Models\User;
class UserComplex extends ComplexSearch
{
public $eloquentModelTable = User::class;
//表头信息
public $headers = [
['value' => 'id', 'label' => '用户id'],
['value' => 'nickname', 'label' => '昵称'],
['value' => 'email', 'label' => '邮箱'],
['value' => 'deleted_at', 'label' => '是否删除'],
['value' => 'created_at', 'label' => '创建时间']
];
//需要隐藏的字段
public $hidden = [
'password','username','email_verified_at'
];
//支持的索引条件
public $conditions = [
'id' => [
'ctype' => 'input',
'display' => true,
'operator' => '=',
'label' => '会员ID',
],
'nickname' => [
'ctype' => 'input',
'display' => true,
'operator' => '=',
'label' => '用户昵称',
'custom' => true,
],
'created_at' => [
'ctype' => 'date-in',
'display' => true,
'format' => 'Y-m-d H:i:s',
'label' => '创建时间',
'custom' => true
],
];
public function query()
{
parent::query();
}
}
如何使用
public function index10()
{
$params = [
'page' => 1,
'pageSize' => 10,
'params' => [
[
'created_at','section',[
'2022-05-16 13:55:36','2022-05-17 11:35:40'
]
]
]
];
$seach = new UserComplex();
return [
'code' => 0,
'message' => 'success',
'result' => $seach->make($params)->get()
];
}