Skip to content

Commit ac7c196

Browse files
committed
LazyCollection类增加page方法简化数据处理
1 parent 83108f8 commit ac7c196

File tree

2 files changed

+136
-0
lines changed

2 files changed

+136
-0
lines changed

src/db/LazyCollection.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,27 @@ public function skip(int $offset)
192192
});
193193
}
194194

195+
/**
196+
* 分页获取数据
197+
* @param int $page 页码(从1开始)
198+
* @param int $listRows 每页数量
199+
* @return static
200+
*/
201+
public function page(int $page, int $listRows = 15)
202+
{
203+
if ($page < 1) {
204+
throw new \InvalidArgumentException('Page should be at least 1');
205+
}
206+
207+
if ($listRows < 1) {
208+
throw new \InvalidArgumentException('Per page should be at least 1');
209+
}
210+
211+
$offset = ($page - 1) * $listRows;
212+
213+
return $this->skip($offset)->take($listRows);
214+
}
215+
195216
/**
196217
* 扁平化集合
197218
* @param int|float $depth 深度

tests/orm/LazyCollectionTest.php

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,4 +678,119 @@ public function testMakeEdgeCases()
678678
$this->assertEquals([1, 2], $lazy->toArray());
679679
}
680680

681+
/**
682+
* 测试page方法
683+
*/
684+
public function testPage()
685+
{
686+
$lazy = LazyCollection::make(range(1, 20));
687+
688+
// 测试第一页
689+
$page1 = $lazy->page(1, 5);
690+
$this->assertEquals([1, 2, 3, 4, 5], $page1->toArray());
691+
692+
// 测试第二页
693+
$page2 = $lazy->page(2, 5);
694+
$this->assertEquals([5 => 6, 6 => 7, 7 => 8, 8 => 9, 9 => 10], $page2->toArray());
695+
696+
// 测试第三页
697+
$page3 = $lazy->page(3, 5);
698+
$this->assertEquals([10 => 11, 11 => 12, 12 => 13, 13 => 14, 14 => 15], $page3->toArray());
699+
700+
// 测试最后一页
701+
$page4 = $lazy->page(4, 5);
702+
$this->assertEquals([15 => 16, 16 => 17, 17 => 18, 18 => 19, 19 => 20], $page4->toArray());
703+
704+
// 测试超出范围的页码
705+
$page5 = $lazy->page(5, 5);
706+
$this->assertEquals([], $page5->toArray());
707+
708+
// 测试默认每页数量
709+
$pageDefault = $lazy->page(1);
710+
$this->assertCount(15, $pageDefault->toArray());
711+
}
712+
713+
/**
714+
* 测试page方法的异常情况
715+
*/
716+
public function testPageValidation()
717+
{
718+
$lazy = LazyCollection::make(range(1, 10));
719+
720+
// 测试无效的页码
721+
$this->expectException(\InvalidArgumentException::class);
722+
$this->expectExceptionMessage('Page should be at least 1');
723+
$lazy->page(0, 5);
724+
}
725+
726+
/**
727+
* 测试page方法的每页数量验证
728+
*/
729+
public function testPagePerPageValidation()
730+
{
731+
$lazy = LazyCollection::make(range(1, 10));
732+
733+
// 测试无效的每页数量
734+
$this->expectException(\InvalidArgumentException::class);
735+
$this->expectExceptionMessage('Per page should be at least 1');
736+
$lazy->page(1, 0);
737+
}
738+
739+
/**
740+
* 测试page方法与其他方法的链式调用
741+
*/
742+
public function testPageChaining()
743+
{
744+
$lazy = LazyCollection::make(range(1, 30));
745+
746+
// 先过滤再分页
747+
$result = $lazy
748+
->filter(function ($value) {
749+
return $value % 2 == 0;
750+
})
751+
->page(2, 5)
752+
->toArray();
753+
754+
// 第二页应该是 12, 14, 16, 18, 20
755+
$this->assertEquals([11 => 12, 13 => 14, 15 => 16, 17 => 18, 19 => 20], $result);
756+
757+
// 先分页再映射
758+
$result = $lazy
759+
->page(1, 3)
760+
->map(function ($value) {
761+
return $value * 10;
762+
})
763+
->toArray();
764+
765+
$this->assertEquals([10, 20, 30], $result);
766+
}
767+
768+
/**
769+
* 测试page方法的惰性执行
770+
*/
771+
public function testPageLaziness()
772+
{
773+
$count = 0;
774+
$generator = function () use (&$count) {
775+
for ($i = 1; $i <= 100; $i++) {
776+
$count++;
777+
yield $i;
778+
}
779+
};
780+
781+
$lazy = new LazyCollection($generator);
782+
$page = $lazy->page(2, 10);
783+
784+
// 还没有执行,不应该生成任何元素
785+
$this->assertEquals(0, $count);
786+
787+
// 转换为数组时才执行
788+
$result = $page->toArray();
789+
790+
// 应该只生成到第20个元素(跳过10个,获取10个)
791+
// 注意:由于skip的实现方式,需要先生成前10个元素才能跳过它们
792+
$this->assertLessThanOrEqual(21, $count); // 可能会多生成一个用于判断结束
793+
$this->assertEquals(range(11, 20), array_values($result));
794+
}
795+
681796
}

0 commit comments

Comments
 (0)