Hyperf分页需手动指定数据库连接实例,不能直接用Db::table()->paginate()。应通过Db::connection('name')->table()->paginate()调用,并可封装为带连接名参数的服务方法。

Hyperf 中分页查询默认使用主数据库连接,若需绑定指定数据库连接(如读库、分库或测试库),关键在于手动指定 Connection 实例并传入查询构建器,再交由 Paginator 处理。Hyperf 本身不提供“自动切换连接的分页”语法糖,需显式构造查询上下文。
1. 获取指定名称的数据库连接实例
Hyperf 的 Db 组件支持多连接配置(在 config/autoload/databases.php 中定义),可通过 Db::connection('connection_name') 获取对应连接对象:
// 示例:获取名为 'slave' 的从库连接
use Hyperf\Database\Connection;
use Hyperf\DbConnection\Db;
$connection = Db::connection('slave'); // 注意:必须是已配置的 connection 名称
2. 使用该连接构建查询并执行分页
不能直接对 Db::table() 调用 paginate()(它固定走默认连接),而应通过 $connection->table() 构建查询,再调用 paginate():
// ✅ 正确方式:绑定指定连接进行分页
use Hyperf\Paginator\Paginator;
$perPage = 10;
$page = (int) $request->input('page', 1);
$result = $connection
->table('users')
->where('status', 1)
->orderBy('id', 'desc')
->paginate($perPage, ['*'], 'page', $page);
// 返回结果与标准 Paginator 一致,支持 toArray()、render() 等
return $this->response->success($result->toArray());
3. 封装成可复用的服务方法(推荐)
为避免重复写连接获取逻辑,建议封装一个带连接名参数的分页服务:
// app/Service/DatabasePaginatorService.php
<?php namespace App\Service;
use Hyperf\DbConnection\Db;
use Hyperf\Paginator\Paginator;
class DatabasePaginatorService
{
public function paginate(string $connectionName, string $table, array $conditions = [], int $perPage = 15, string $pageName = 'page', int $currentPage = 1, array $columns = ['*'])
{
$connection = Db::connection($connectionName);
$query = $connection->table($table)->select($columns);
foreach ($conditions as $column => $value) {
$query->where($column, $value);
}
return $query->paginate($perPage, $columns, $pageName, $currentPage);
}
}
// 在 Controller 中使用:
// $paginator = $this->container->get(DatabasePaginatorService::class)->paginate('slave', 'users', ['status' => 1]);
4. 注意事项与常见问题
确保以下几点,否则会报错或走错连接:
- 配置文件
config/autoload/databases.php中已正确定义目标连接(如'slave'),且default键未覆盖它 - 不要混用
Db::table()和$connection->table()—— 前者永远走默认连接 - 分页参数
$page需手动获取并校验(如max(1, (int)$request->input('page'))),避免 SQL 注入或越界 - 若使用 Eloquent 模型,需在模型中指定
protected $connection = 'slave';,再调用Model::paginate()











