php yield使用以及优点和场景
php yield 使用,原生php在使用yield中还是比较少的,但还是很有学习的价值,如果后面去认识协程编程有很大帮助
优点
- 目前根据我使用的场景来看,yield协程操作可以改变执行流程,比如封装分批查询表中所有数据,查出目录下所有文件等等,外层只需要通过foreach来循环获得
- 避免一次性获取大批量数据节省内存消耗
1 php官网yield相关知识点
-
yield正常使用
function generate() { yield 1; yield 2; yield 3; } foreach(generate() as $row) { echo $row, "\n"; } # 1 # 2 # 3
-
yield 返回键值对
function generate() { yield 88 => chr(1); } foreach(generate() as $key => $row) { echo "{$key} => {$row}", "\n"; } # 88 => X
-
引用生成值
function &gen_reference() { $value = 3; while ($value > 0) { yield $value; } } /* * 我们可以在循环中修改$number的值, * 而生成器是使用的引用值来生成, * 所以gen_reference()内部的$value值也会跟着变化。 */ foreach (gen_reference() as &$number) { echo (--$number).'... '; }
-
yield from使用
php7.0之后引入的,如果你的环境是php5.6的话,直接return调用即可
function generate() { yield 1; yield from generate2(); } function generate2() { yield 2; } foreach(generate() as $row) { echo $row, "\n"; } # 1 # 2
2 项目中使用
-
数据库查询所有数据,使用yield来分页
# 就拿最原始的数据库操作来示范 # 生产中执行SQL最好先使用预处理 public function getByChunk($sql, $limit=1000) { $offset = 0; while (true) { $tmpSql = $sql. " limit {$offset}, {$limit}"; $rows = $this->getAll($tmpSql); # 没查出信息,相当于末页 if (empty($rows)) { return ; } yield $rows; # 没有返回等量的数据,相当于末页了 if (count($rows) < $limit) { return ; } $offset += $limit; # 实际上如果分页过大查询效率也是大大降低 # 如果sql中有ID,建议 使用last ID + order by ID asc来优化 } }
-
迭代目录
function dir($path) { try { $d = dir($path); while (false !== ($entry = $d->read())) { if (in_array($entry , ['.' , '..'])) { continue; } yield $entry; } } finally { $d->close(); } }
-
循环处理返回大文件内容等
3 协程开发
yield本质就是在当前进程出让cpu执行权利给本进程其他地方执行, 如此我们可以做一些非阻塞操作,这样子大大提高cpu利用率。