chunk 和 chunkById 功能上有区别吗?

InstallmentItem::query()->chunk(100,function(){});
InstallmentItem::query()->chunkById(100,function(){});
桃知夭夭
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 14
leo

这种问题为什么不自己看一看源码呢?

6年前 评论

@leo 好吧,有点懒了,昨天。:smile:

6年前 评论

@leo 因为公司现有的项目中用的是laravel5.1,这个版本里面还没有chunkById,那么我想处理大表 带条件的更新操作时chunk会丢数据,我应该怎么实现呢,leo哥能否给个思路。~

5年前 评论
leo

@AmberLavigne 照着 chunkById 的代码写一下不就可以了么

5年前 评论

@leo :joy:想想也是,研究研究~~~

5年前 评论

自问自答: 实现chunkById() 需求处理大表带条件更新操作。 基于laravel5.1 的command

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use DB;
use App\Model\Comment;
class CompletionCommentTitle extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature =' title:completion_comment_title';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '根据指定条件补全评论title';

    const CHUNK_SIZE = 150;
    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        try{
             $this->info('开始处理...');
             $this->chunkById(self::CHUNK_SIZE,function ($comments){
                 $this->info(sprintf('正在补全 ID 范围为 %s 至 %s 的评论title',$comments->first()->id, $comments->last()->id));
                 foreach($comments as $comment){
                     $comment->where('id',$comment->id)->update(['title'=> $this->perpareTitle()]);
                 }
             });
            $this->info('处理结束...');
        }catch(\Exception $e){
            $this->error($e->getMessage() . ',Line:' . $e->getLine());
        }
    }

    /**
     * 需要补全的理出数据
     * @return mixed
     * @throws \Exception
     */
    protected function perpareTitle(){

        $title_arr = [
            'Very flattering',
            'Super cute!',
             'Very nice',
            'Very good',
            'Satisfying',
            'Nice looking',
            'I love it',
            'Fit perfectly',
            'So comfy',
            'Nice',
            'Perfect!',
            'Look very pretty!',
            'Fit very well',
            'Look good',
            'Fantastic',
            'Comfortable',
            'Thanks',
            'Nice material',
            'Good fit',
            'It\'s cute',
            'Good looking',
            'Speedy delivery',
            'So nice and pretty',
            'Well received!',
            'Great quality',
            'Great purchase!',
            'so well made',
            'Very fashionable',
            'Beautiful',
            'High quality',
            'Highly recommend',
            'nice looking',
            'True size',
            'Adorable',
            'Awesome.',
            'nicely made',
            'Feel good on',
            'Excellent',
            'Super comfy!',
            'Fit as expected'
        ];

        $random =  random_int(0,39);
        return $title_arr[$random];
    }

    /**
     * ID分块处理核心代码
     * @param $count
     * @param callable $callback
     * @param string $column
     * @return bool
     */
    protected function chunkById($count, callable $callback, $column = 'id'){
        $lastId = 0;
        do {
            $results = $this->forPageAfterId($count, $lastId, $column)->get();
            $countResults = $results->count();
            if ($countResults == 0){
                break;
            }
            if ($callback($results) === false) {
                return false;
            }
            $lastId = $results->last()->{$column};
            unset($results);
        } while ($countResults == $count);

        return true;
    }

    protected function forPageAfterId($perPage = 15, $lastId = 0, $column = 'id')
    {
        return Comment::query()
            ->where('title','')
            ->where('customer_id',0)
            ->where($column, '>', $lastId)
            ->orderBy($column, 'asc')
            ->take($perPage);
    }
}
5年前 评论

@leo file 老师请教个问题,我使用chunkById批量处理数据报错,但是chunk方法没问题。报错信息In Builder.php line 591:
Illegal operator and value combination.

5年前 评论
leo

@等车的猪 贴代码

5年前 评论

@leo

 MessageLog1::query()->select('orderId', 'shopId')->chunkById(self::CHUNK_SIZE, function ($rows) {
            foreach ($rows as $row) {
//                dd($row->shopId);
                if (!empty($row)) {
                    $shop = Shop::query()->where('shopId', $row->shopId)->first();
                    if ($shop) {
                        CommentsJob::dispatch(['orderId' => $row->orderId, 'brandUserId' => $shop->brandUserId, 'shopId' => $row->shopId]);
                    }
                }
            }
        });

如果改成chunk就不会出问题,表结构也是id自增

5年前 评论
leo

@等车的猪 你的 select() 里需要加上 id 字段

5年前 评论

@leo 好的 老师厉害了。我先试试

5年前 评论

chunkbyid不能用于join情况

5年前 评论
小李世界 2年前

chunkbyid 使用join
'id' in where clause is ambiguous
如果指定id:表名.id,也报错,貌似chunkbyid不支持加表名指定,forPageAfterId(1000, NULL, 'r_svr.id')

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!