You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CursorPaginator测试异常求助:仅测试环境报错,浏览器特定条目数失效

解决CursorPaginator测试报错:Only arrays and objects are supported when cursor paginating items.

结合你的场景,我分享下排查思路和可能的解决方案,我之前也遇到过类似的诡异问题:

1. 先确认排序字段的数据库存储精度

你提到已经确认创建时间的毫秒数不同,但要注意:如果你的entries表中created_at字段不是datetime(6)(支持毫秒存储)类型,数据库会自动截断毫秒部分,导致实际存储的时间仍可能重复。

CursorPaginator完全依赖排序字段的唯一性来生成游标,如果排序值重复,在分页到非满页(比如6条数据分两页,第二页仅1条)时,内部可能出现数据结构异常,触发这个类型错误。

检查与修复:

  • 查看entries表的迁移文件,确认时间字段定义:
    $table->datetime('created_at')->useCurrent()->precision(6);
    $table->datetime('updated_at')->useCurrent()->useCurrentOnUpdate()->precision(6);
    
  • 如果之前没有设置precision(6),修改迁移并重新执行(记得备份数据)。

2. 排查through方法的潜在影响

你在控制器中用through给模型添加额外属性,虽然看起来返回的是模型实例,但CursorPaginator在处理分页数据时,对through后的集合有特殊的内部逻辑,尤其是在处理单条数据的非满页场景下,可能触发类型识别异常。

替代方案:

把额外属性的逻辑移到模型层面,避免在分页器中修改实例:

// Entry模型中添加
protected $appends = ['can_edit', 'can_delete'];

public function getCanEditAttribute()
{
    return auth()->user()?->can('update', $this->content);
}

public function getCanDeleteAttribute()
{
    return auth()->user()?->can('delete', $this->content);
}

然后简化控制器代码:

return $item->entries() 
    ->latest() 
    ->with(['content','user']) 
    ->cursorPaginate(5) 
    ->withPath("/items/$item->id/notes/more");

3. 测试中打印请求详情定位问题

在测试代码中添加日志,确认第二页的请求参数和返回数据结构:

public function testMoreNotesAreReturnedIfRequested() { 
    $item = Item::factory()->has(Entry::factory()->for($this->user)->count(6))->create(); 
    $response = $this->actingAs($this->user)->json('get',"/items/{$item->id}/notes/more"); 
    $nextUrl = $response->decodeResponseJson()['next_page_url'];
    
    // 打印URL检查游标参数是否正常
    dump($nextUrl);
    
    $next = $this->actingAs($this->user)->json('get',$nextUrl); 
    
    // 打印返回内容,确认data字段的结构
    dump($next->decodeResponseJson());
    
    $next->assertJson(fn (AssertableJson $json) => $json 
        ->has('data') 
        ->has('paginator')); 
}

如果data字段是空或非集合类型,那大概率是游标查询的逻辑出了问题。

4. 查看测试环境的实际查询语句

开启Laravel查询日志,看看第二页的游标查询是否符合预期:

// 在测试中添加
DB::enableQueryLog();
$next = $this->actingAs($this->user)->json('get',$nextUrl); 
dump(DB::getQueryLog());

通过日志可以确认CursorPaginator生成的查询是否正确过滤了数据,有没有出现不符合预期的结果。

为什么浏览器只在特定条目数失效?

这是因为6、7、16、17这类条目数会生成非满页的第二页(比如6条数据分两页,第二页仅1条),此时CursorPaginator的内部处理逻辑更容易触发隐藏bug;而满页场景(比如10条数据分两页,每页5条)不会触发这个问题。


内容的提问来源于stack exchange,提问作者Rory

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 02:37:48