madong/query

The Madong Query component - A powerful query parameter parsing and filtering library

Maintainers

Package info

gitcode.com/motion-code/query

pkg:composer/madong/query

Statistics

Installs: 3

Dependents: 0

Suggesters: 0

1.0.1 2026-03-11 03:46 UTC

This package is auto-updated.

Last update: 2026-03-11 08:19:45 UTC


README

一个强大的查询参数解析和过滤库,为 PHP 8.1+ 项目提供灵活、类型安全的查询构建能力。

✨ 特性

  • 🚀 高性能: 轻量级设计,最小化性能开销
  • 🔒 类型安全: 使用 PHP 8.1+ 枚举提供编译时类型检查
  • 🎯 灵活配置: 支持多种查询模式和参数格式
  • 🛠 易于集成: 提供多种集成方式(Trait、依赖注入、门面)
  • 📝 优雅 API: 直观的接口设计,降低学习成本
  • 🧪 完整测试: 全面的测试覆盖
  • 📦 零依赖: 仅依赖 Illuminate 组件
  • 🎛 高度可配置: SelectInput 支持字段过滤、格式限定、自定义返回格式等

📦 安装

通过 Composer 安装:

composer require madong/query

环境要求

  • PHP >= 8.1
  • illuminate/database >= 11.0
  • illuminate/pagination >= 11.0

🚀 快速开始

基本使用

use madong\query\QueryParamsManager;

// 创建管理器实例
$manager = new QueryParamsManager();

// 应用查询参数
$query = $manager->apply(User::query(), [
    'filters' => [
        ['field' => 'name', 'operator' => 'like', 'value' => 'John'],
        ['field' => 'age', 'operator' => 'gt', 'value' => 18]
    ],
    'sort' => ['created_at' => 'desc'],
    'limit' => 20
]);

// 获取结果
$users = $query->get();

使用 Trait(推荐)

在 Controller 中使用:

use madong\query\traits\WithQueryParams;

class UserController extends Controller
{
    use WithQueryParams;

    public function index(Request $request)
    {
        $params = $request->all();
        
        return $this->paginateWithParams(User::query(), $params, [
            'keyword_fields' => ['name', 'email']
        ]);
    }
}

使用门面(CLI 环境)

use madong\query\QueryFacade;

$result = QueryFacade::paginate(User::class, $params);

📖 核心概念

查询参数格式

支持多种查询参数格式:

1. 标准 filters 格式

$params = [
    'filters' => [
        ['field' => 'name', 'operator' => 'like', 'value' => 'John'],
        ['field' => 'status', 'operator' => 'eq', 'value' => 'active']
    ]
];

2. 大写前缀格式

$params = [
    'LIKE_name' => 'John',
    'EQ_status' => 'active'
];

3. 数组格式

$params = [
    ['name', 'like', 'John'],
    ['status', 'eq', 'active']
];

支持的操作符

操作符说明示例
eq等于['field' => 'status', 'operator' => 'eq', 'value' => 'active']
ne不等于['field' => 'status', 'operator' => 'ne', 'value' => 'deleted']
gt大于['field' => 'age', 'operator' => 'gt', 'value' => 18]
gte大于等于['field' => 'age', 'operator' => 'gte', 'value' => 18]
lt小于['field' => 'age', 'operator' => 'lt', 'value' => 60]
lte小于等于['field' => 'age', 'operator' => 'lte', 'value' => 60]
like模糊匹配['field' => 'name', 'operator' => 'like', 'value' => 'John']
ilike不区分大小写模糊匹配['field' => 'name', 'operator' => 'ilike', 'value' => 'john']
in包含['field' => 'id', 'operator' => 'in', 'value' => [1, 2, 3]]
not_in不包含['field' => 'id', 'operator' => 'not_in', 'value' => [4, 5, 6]]
between范围['field' => 'price', 'operator' => 'between', 'value' => [10, 100]]
not_between非范围['field' => 'price', 'operator' => 'not_between', 'value' => [10, 100]]
null为空['field' => 'deleted_at', 'operator' => 'null']
not_null不为空['field' => 'deleted_at', 'operator' => 'not_null']

枚举类型

Operator 枚举

use madong\query\enum\Operator;

$operator = Operator::LIKE;
echo $operator->value; // 输出: like

QueryMode 枚举

use madong\query\enum\QueryMode;

$mode = QueryMode::STANDARD; // 标准模式
$mode = QueryMode::STRICT;   // 严格模式

ParamFormat 枚举

use madong\query\enum\ParamFormat;

$format = ParamFormat::FILTERS;   // 标准 filters 格式
$format = ParamFormat::UPPERCASE; // 大写前缀格式
$format = ParamFormat::ARRAY;     // 三元素数组格式
$format = ParamFormat::WHERE;     // 直接 where 条件格式
$format = ParamFormat::AUTO;      // 自动检测格式

🎯 高级用法

自定义查询选项

$manager->apply(User::query(), $params, [
    'allowed_fields' => ['name', 'email', 'status'],  // 允许查询的字段
    'keyword_fields' => ['name', 'email'],            // 关键词搜索字段
    'default_sort' => ['created_at' => 'desc'],       // 默认排序
    'default_page' => 1,                              // 默认页码
    'default_page_size' => 20,                        // 默认每页数量
    'max_page_size' => 100                            // 最大每页数量
]);

关键词搜索

$params = [
    'keyword' => 'John',
    'keyword_fields' => ['name', 'email', 'phone']
];

// 自动在指定字段中进行模糊搜索
$users = $manager->all(User::query(), $params, [
    'keyword_fields' => ['name', 'email']
]);

分页查询

$result = $manager->paginate(User::query(), [
    'filters' => [
        ['field' => 'status', 'operator' => 'eq', 'value' => 'active']
    ],
    'page' => 1,
    'page_size' => 20
], [
    'keyword_fields' => ['name', 'email']
]);

// 返回格式
[
    'data' => [...],           // 数据列表
    'total' => 100,            // 总数
    'page' => 1,               // 当前页
    'page_size' => 20,         // 每页数量
    'last_page' => 5           // 最后一页
]

排序

$params = [
    'sort' => [
        'created_at' => 'desc',  // 降序
        'name' => 'asc'          // 升序
    ]
];

多层查询

$params = [
    'filters' => [
        ['field' => 'status', 'operator' => 'eq', 'value' => 'active'],
        ['field' => 'age', 'operator' => 'gt', 'value' => 18],
        ['field' => 'name', 'operator' => 'like', 'value' => 'John']
    ]
];

🔧 集成方式

1. Controller 集成

use madong\query\traits\WithQueryParams;

class AdminController extends Controller
{
    use WithQueryParams;

    public function index(Request $request)
    {
        return $this->paginateWithParams(User::query(), $request->all(), [
            'keyword_fields' => ['name', 'email']
        ]);
    }
}

2. Service 集成

use madong\query\traits\WithServiceQuery;

class UserService extends BaseService
{
    use WithServiceQuery;

    public function getList(array $params): array
    {
        return $this->paginateWithParams(User::query(), $params, [
            'allowed_fields' => ['name', 'email', 'status']
        ]);
    }
}

3. DAO 集成

use madong\query\traits\WithDaoQuery;

class UserDao extends BaseDao
{
    use WithDaoQuery;

    public function search(array $params): Collection
    {
        return $this->allWithParams($this->getModel(), $params);
    }
}

4. 依赖注入

use madong\query\QueryParamsManager;

class UserController extends Controller
{
    public function __construct(
        private QueryParamsManager $queryParams
    ) {}

    public function index(Request $request)
    {
        return $this->queryParams->paginate(User::query(), $request->all());
    }
}

5. SelectInput 集成(灵活参数解析)

WithSelectInput Trait 提供高度可配置的参数解析功能,适用于需要精确控制的场景。

基本使用

use madong\query\traits\WithSelectInput;

class UserController extends Controller
{
    use WithSelectInput;

    public function index(Request $request)
    {
        // 使用默认配置,返回标准格式
        [$where, $format, $limit, $field, $order, $page] = $this->selectInput($request);

        // 查询数据
        $list = User::where($where)
            ->orderByRaw($order)
            ->paginate($limit, ['*'], 'page', $page);

        return response()->json($list);
    }
}

自定义配置

use madong\query\traits\WithSelectInput;
use madong\query\QuerySelectConfig;

class UserController extends Controller
{
    use WithSelectInput;

    public function index(Request $request)
    {
        // 创建自定义配置
        $config = QuerySelectConfig::make([
            'allowed_fields' => ['name', 'email', 'status', 'created_at'],
            'skip_fields' => ['password', 'token', 'deleted_at'],
            'keyword_fields' => ['name', 'email'],
            'enable_keyword_search' => true,
            'sort_fields' => ['name', 'email', 'created_at'],
            'default_sort' => ['created_at' => 'desc'],
            'default_page_size' => 20,
            'max_page_size' => 100,
        ]);

        // 使用自定义配置
        $result = $this->selectInputWithConfig($request, $config);
        $where = $result['where'];
        $order = $result['order'];
        // ...
    }
}

配置选项

选项类型默认值说明
return_formatstring'array'返回格式:arrayobjectcompact
param_formatstring'auto'参数格式:filtersuppercasearraywhereauto
allowed_fieldsarray\|nullnull允许的字段白名单
skip_fieldsarray[]跳过的字段黑名单
sort_fieldsarray\|nullnull允许排序的字段
default_sortarray[]默认排序规则
default_page_sizeint10默认每页数量
max_page_sizeint100最大每页数量
default_pageint1默认页码
keyword_fieldsarray[]关键词搜索字段
enable_keyword_searchboolfalse是否启用关键词搜索
keyword_paramstring'keyword'关键词参数名
enable_range_querybooltrue是否启用范围查询
enable_like_querybooltrue是否启用模糊匹配
auto_convert_datetimebooltrue是否自动转换日期时间
skip_empty_valuesbooltrue是否跳过空值
debug_modeboolfalse是否启用调试模式

在 Crud 中使用(推荐)

class UserController extends Crud
{
    // 类属性配置
    protected ?array $selectInputConfig = [
        'allowed_fields' => ['name', 'email', 'status'],
        'skip_fields' => ['password', 'token'],
        'sort_fields' => ['name', 'created_at'],
        'default_sort' => ['created_at' => 'desc'],
    ];

    public function index(Request $request)
    {
        // 自动使用类属性配置
        [$where, $format, $limit, $field, $order, $page] = $this->selectInput($request);
        // ...
    }

    public function search(Request $request)
    {
        // 临时传入配置,不影响其他方法
        [$where, $format, $limit, $field, $order, $page] = $this->selectInput($request, [
            'keyword_fields' => ['name', 'email'],
            'enable_keyword_search' => true,
        ]);
        // ...
    }
}

配置优先级:方法参数配置 > 类属性配置 > 默认配置

🛠️ 核心类

QueryParamsManager

查询参数管理器,提供统一的查询处理入口。

use madong\query\QueryParamsManager;

$manager = new QueryParamsManager();

// 应用查询参数
$query = $manager->apply($modelOrQuery, $params, $options);

// 解析查询参数
$parsed = $manager->parse($params);

// 分页查询
$result = $manager->paginate($modelOrQuery, $params, $options);

// 查询所有
$all = $manager->all($modelOrQuery, $params, $options);

// 查询第一条
$first = $manager->first($modelOrQuery, $params, $options);

QueryCondition

查询条件对象,封装单个查询条件。

use madong\query\QueryCondition;

$condition = new QueryCondition('name', 'like', 'John');
echo $condition->field;    // name
echo $condition->operator; // like
echo $condition->value;    // John

// 静态工厂方法
$condition = QueryCondition::eq('status', 'active');
$condition = QueryCondition::like('name', 'John');
$condition = QueryCondition::in('id', [1, 2, 3]);

QueryParamParser

查询参数解析器,支持多种参数格式。

use madong\query\QueryParamParser;

$parser = new QueryParamParser();

// 解析参数
$conditions = $parser->parse($params);

QueryBuilderHelper

查询构建器辅助类,应用查询条件到构建器。

use madong\query\QueryBuilderHelper;

$helper = new QueryBuilderHelper();

$query = $helper->apply($query, $params, $options);

QueryParamConverter

参数转换器,转换不同格式的参数。

use madong\query\QueryParamConverter;

$converter = new QueryParamConverter();

// 转换为标准格式
$standard = $converter->toStandard($params);

// 转换为数组格式
$array = $converter->toArray($params);

QueryFacade

门面类,提供静态访问接口(适用于 CLI 环境)。

use madong\query\QueryFacade;

$result = QueryFacade::paginate(User::class, $params);

🧪 异常处理

QueryException

基础查询异常。

use madong\query\exception\QueryException;

try {
    // 查询操作
} catch (QueryException $e) {
    // 处理异常
}

QueryParseException

查询参数解析异常。

use madong\query\exception\QueryParseException;

try {
    $manager->apply(User::query(), $params);
} catch (QueryParseException $e) {
    // 处理解析异常
}

📚 完整示例

用户管理接口

namespace App\Http\Controllers;

use madong\query\traits\WithQueryParams;
use App\Models\User;

class UserController extends Controller
{
    use WithQueryParams;

    public function index(Request $request)
    {
        $params = $request->all();
        
        $options = [
            'allowed_fields' => ['name', 'email', 'status', 'created_at'],
            'keyword_fields' => ['name', 'email'],
            'default_sort' => ['created_at' => 'desc'],
            'default_page_size' => 20,
            'max_page_size' => 100
        ];
        
        return $this->paginateWithParams(User::query(), $params, $options);
    }

    public function show($id, Request $request)
    {
        $params = $request->all();
        
        return $this->firstWithParams(User::query(), array_merge($params, [
            'filters' => [['field' => 'id', 'operator' => 'eq', 'value' => $id]]
        ]));
    }
}

高级查询示例

$params = [
    'filters' => [
        ['field' => 'status', 'operator' => 'eq', 'value' => 'active'],
        ['field' => 'age', 'operator' => 'between', 'value' => [18, 60]],
        ['field' => 'name', 'operator' => 'like', 'value' => 'John'],
        ['field' => 'created_at', 'operator' => 'gte', 'value' => '2024-01-01']
    ],
    'sort' => [
        'created_at' => 'desc',
        'name' => 'asc'
    ],
    'page' => 1,
    'page_size' => 20
];

$result = $manager->paginate(User::query(), $params);

关键词搜索示例

$params = [
    'keyword' => 'John Doe',
    'keyword_fields' => ['name', 'email', 'phone']
];

$users = $manager->all(User::query(), $params, [
    'keyword_fields' => ['name', 'email', 'phone']
]);

🎨 最佳实践

1. 使用 Trait 简化代码

// 推荐
class UserController extends Controller
{
    use WithQueryParams;

    public function index(Request $request)
    {
        return $this->paginateWithParams(User::query(), $request->all());
    }
}

// 不推荐
class UserController extends Controller
{
    public function index(Request $request)
    {
        $manager = new QueryParamsManager();
        return $manager->paginate(User::query(), $request->all());
    }
}

2. 配置允许查询的字段

$options = [
    'allowed_fields' => ['name', 'email', 'status']  // 只允许这些字段
];

3. 设置分页限制

$options = [
    'default_page_size' => 20,
    'max_page_size' => 100  // 防止查询过多数据
];

4. 使用关键词搜索

$options = [
    'keyword_fields' => ['name', 'email']  // 指定搜索字段
];

🔒 安全建议

  1. 限制允许查询的字段: 使用 allowed_fields 选项
  2. 设置分页上限: 使用 max_page_size 选项
  3. 验证输入数据: 对用户输入进行验证
  4. 使用参数绑定: 底层自动使用参数绑定防止 SQL 注入

📄 许可证

Apache-2.0 License

👨‍💻 作者

Mr. April - 405784684@qq.com

🌐 官方网站

http://www.madong.tech

🤝 贡献

欢迎提交 Issue 和 Pull Request!

📞 支持

如有问题,请提交 Issue 或联系作者。