@@ -536,6 +536,10 @@ public function cursor($data = null)
536536 */
537537 public function chunk (int $ count , callable $ callback , string | array | null $ column = null , string $ order = 'asc ' ): bool
538538 {
539+ if ($ count < 1 ) {
540+ throw new Exception ('The chunk size should be at least 1 ' );
541+ }
542+
539543 $ options = $ this ->getOptions ();
540544 $ column = $ column ?: $ this ->getPk ();
541545
@@ -560,11 +564,15 @@ public function chunk(int $count, callable $callback, string | array | null $col
560564
561565 $ resultSet = $ query ->order ($ column , $ order )->select ();
562566
563- while (count ( $ resultSet ) > 0 ) {
567+ while (true ) {
564568 if (false === call_user_func ($ callback , $ resultSet )) {
565569 return false ;
566570 }
567571
572+ if (count ($ resultSet ) < $ count ) {
573+ break ;
574+ }
575+
568576 if (isset ($ times )) {
569577 $ times ++;
570578 $ query = $ this ->options ($ options )->page ($ times , $ count );
@@ -582,4 +590,44 @@ public function chunk(int $count, callable $callback, string | array | null $col
582590
583591 return true ;
584592 }
593+
594+ /**
595+ * 惰性分批遍历数据
596+ * @param int $count 每批处理的数量
597+ * @param string|null $column 分批处理的字段名
598+ * @param string $order 字段排序
599+ * @return \Generator
600+ */
601+ public function lazy (int $ count = 1000 , ?string $ column = null , string $ order = 'desc ' )
602+ {
603+ if ($ count < 1 ) {
604+ throw new Exception ('The chunk size should be at least 1 ' );
605+ }
606+
607+ $ limit = (int )$ this ->getOption ('limit ' , 0 );
608+ $ column = $ column ?: $ this ->getPk ();
609+ $ this ->order ($ column , $ order )->limit ($ count > $ limit ? $ limit : $ count );
610+
611+ $ options = $ this ->getOptions ();
612+ $ bind = $ this ->bind ;
613+ $ times = 0 ;
614+ $ resultSet = $ this ->options ($ options )->select ();
615+
616+ while (true ) {
617+ foreach ($ resultSet as $ item ) {
618+ yield $ item ;
619+ $ lastId = $ item [$ column ];
620+ $ times ++;
621+ }
622+
623+ if (count ($ resultSet ) < $ count || ($ limit && $ times >= $ limit )) {
624+ break ;
625+ }
626+
627+ $ resultSet = $ this ->options ($ options )
628+ ->where ($ column , 'asc ' == strtolower ($ order ) ? '> ' : '< ' , $ lastId )
629+ ->bind ($ bind )
630+ ->select ();
631+ };
632+ }
585633}
0 commit comments