Laravel 8.x Eloquent模型调用setConnection后分页功能失效如何解决
问题原因
首先明确:Laravel的分页功能本身不会主动重置数据库连接,你遇到的问题是动态设置模型实例连接的写法不兼容分页的查询逻辑导致的。
分页执行时会发起两次查询:
- 第一次是带条件的count查询,用于统计总记录数,计算总页数
- 第二次是带分页参数的实际数据查询
你通过实例化模型后调用setConnection的方式,仅作用于当前模型实例生成的首次查询构建器,count查询在初始化时没有继承你动态设置的连接,就会默认使用项目全局默认的test数据库连接,从而抛出表不存在的错误。
解决方案
方案1:使用on方法静态指定连接(最推荐)
Laravel的Eloquent模型提供了on静态方法,直接指定本次查询使用的连接,该连接会被后续所有查询(包括分页的count查询、关联预加载查询)继承,修正后的控制器代码如下:
public function getStats(Request $request) { // 直接用on方法指定连接,替代实例化后setConnection的写法 $query = Time::on('mysql_timer')->with(['user' => function ($q) { // 如果User模型也存储在mysql_timer库,需要给关联查询也指定连接 $q->on('mysql_timer'); }]); $data = $query->paginate($length); dd($data); }
方案2:修改模型默认连接属性
如果你的Time模型大部分场景下都是用mysql_timer连接,可以直接在模型中声明$connection属性,不需要动态设置:
class Time extends Model { use HasFactory; // 直接指定默认连接 protected $connection = 'mysql_timer'; protected $table = 'times'; public $timestamps = false; protected $primaryKey = 'uid'; // 其余代码保持不变 }
控制器中就不需要额外设置连接,直接写Time::query()->with('user')->paginate($length)即可。
方案3:给查询构建器手动指定连接
如果你确实需要在运行时动态切换连接,也可以直接给查询构建器设置连接:
$query = Time::query()->setConnection('mysql_timer')->with('user');
内容的提问来源于stack exchange,提问作者Anders
相关产品推荐
相关产品推荐

