分析yii2的each()和batch()

  最近从用了2年多的Yii转到了Yii2,读了一遍官方文档以后发现两个比较有趣的新函数,each()和batch()都是归于db方面的,看了下源码然后写了点拙见。
  先看源码,each()和batch()函数都是调用BatchQueryResult这个类,唯一的区别是each这个参数,而这个类它实现了Iterator接口,这也就说明了为什么each和batch都要用foreach来调用。
   分析yii2的each()和batch()_第1张图片
   分析yii2的each()和batch()_第2张图片
  简单说下Iterator,这个接口是PHP预定义的接口,同时它继承于Traversable预定义接口,这个接口唯一的作用就是检测一个类是否可以使用 foreach 进行遍历。
  回过来再看BatchQueryResult这个类,主要的两个可以配置的属性each和batchSize, each就是用来区别each和batch的属性,主要表现在next()这个函数上,仔细看了下代码,其实发现each和batch的区别就是foreach每次取出的数据量,而这个数据量受限于batchSize,默认是100,接下来再看源码又会发现each和batch都是一次性取出上限batchSize的数据,区别只不过是foreach遍历单次输出的数据each是每次一条,batch每次batchSize条。
   分析yii2的each()和batch()_第3张图片
  具体实现细节看fetchData这个函数,这里本质是填充数据,获取数据调用的是 _dataReadeder->read(), 追踪函数会发现其实调用的是PDO::fetch()函数,限制获取数量的条件是batchSize,到这里each()和batch()其实是一样的,具体这两个函数的区别要看next()函数:
   分析yii2的each()和batch()_第4张图片
  理解这里可以先看下官方文档关于foreach调用时的内部实现( https://www.php.net/manual/zh/class.iterator.php),这边可以看出本质上each()和batch()每次都取出batchSize个数据,但是区别是each()在遍历时候每次只取出一个,batch()直接返回batchSize个数据,所以如果对内存有要求不管each()还是batch()都要按需限制下batchSize参数。

你可能感兴趣的:(分析yii2的each()和batch())