现代 PHP 新特性系列(四) —— 生成器的创建和使用 | 新特性 | 现代 PHP 新特性与最佳实践


本站和网页 https://xueyuanjun.com/post/4317.html 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

现代 PHP 新特性系列(四) —— 生成器的创建和使用 | 新特性 | 现代 PHP 新特性与最佳实践
Laravel 学院
文档
Laravel 8.x 中文文档
Laravel 7.x 中文文档
Laravel 6.x 中文文档
Laravel 5.8 中文文档
Laravel 5.7 中文文档
Laravel 5.6 中文文档
Laravel 5.5 中文文档
Laravel 5.4 中文文档
Laravel 5.3 中文文档
Laravel 5.2 中文文档
Laravel 5.1 中文文档
Lumen 中文文档
全栈教程
PHP 全栈工程师指南
PHP 入门到实战
Laravel 入门到精通
Vue.js 入门到实战
玩转 PhpStorm 教程
Laravel 博客入门项目
Laravel 微信小程序项目
Laravel 前后端分离项目
Swoole 入门到实战
Eloquent 性能优化实战
Redis 高性能实战系列
Laravel 新版本特性
PHP 新特性与最佳实践
Golang
Go 入门教程
Go Web 编程
Gin 使用教程
微服务开发
内功修炼
数据结构与算法
网络协议
微服务从入门到实践
高性能 MySQL 实战
高性能 Redis 实战
Laravel 消息队列实战
Laravel 从学徒到工匠
PHP 设计模式系列
名企面试指南
资源库
Laravel 资源大全
Laravel 开源项目
Laravel 扩展包
Laravel 资源下载
更多
博客 & 新闻
问答 & 讨论
Leetcode 题解
学院君读书笔记系列
关于 Laravel 学院
Laravel 互助学习群
Golang 互助学习群
更多
Laravel 中文文档
Laravel 全栈教程
Laravel 学习路径
Go 入门教程
程序员内功修炼
博客
问答
搜索
注册
登录
Info
Content
章节导航
现代 PHP 新特性与最佳实践
目录索引
新特性
9篇文章
现代 PHP 新特性系列(一) —— 命名空间
现代 PHP 新特性系列(二) —— 善用接口
现代 PHP 新特性系列(三) —— Trait 概览
现代 PHP 新特性系列(四) —— 生成器的创建和使用
现代 PHP 新特性系列(五) —— 闭包和匿名函数
现代 PHP 新特性系列(六) —— Zend Opcache
现代 PHP 新特性系列(七) —— 内置的 HTTP 服务器
PHP 8 新特性系列 —— JIT 对 PHP 应用性能的影响
PHP 8 所有新特性一览和代码示例
最佳实践
11篇文章
漫谈 PHP 组件、框架、Composer 那些事
聊聊 PHP 私有组件以及如何创建自己的 PHP 组件
PHP 安全三板斧:过滤、验证和转义之过滤篇 & Laravel底层SQL注入规避
PHP 安全三板斧:过滤、验证和转义之验证篇 & Laravel底层字段验证实现
PHP 安全三板斧:过滤、验证和转义之转义篇 & Blade 模板引擎避免 XSS 攻击原理探究
PHP 开发者如何做好密码保护 & Laravel 底层密码存储和验证实现
PHP 日期、时间和时区处理 API 及组件
PHP 数据库统一处理 API —— PDO 扩展及其在 Laravel 底层的使用
PHP 多字节字符串处理函数及字符编码
PHP 统一资源处理 API —— 流(Stream)的概述与使用详解
深入探讨 PHP 错误异常处理机制及 Laravel 框架底层的相应实现
部署调优
4篇文章
PHP 服务器主机选择及初始化配置 —— 新增用户及密钥对认证
在服务器上对 PHP-FPM 和 Nginx 进行安装配置详解
php.ini 配置调优 —— 让 PHP 应用性能维持在更高水平
使用现代化工具 Capistrano 自动部署 PHP 应用代码到生产环境
番外篇
2篇文章
在 Windows 下安装部署 PHP 7.0 本地开发环境
PHP 7.0 与 PHP 5.6 下 Laravel 博客应用性能对比分析
图书
现代 PHP 新特性与最佳实践
新特性
现代 PHP 新特性系列(四) —— 生成器的创建和使用
现代 PHP 新特性系列(四) —— 生成器的创建和使用
由 学院君 创建于6年前, 最后更新于 3年前
版本号 #1
21403 views
25 likes
0 collects
1、概述
生成器是 PHP 5.5 引入的新特性,但是目测很少人用到它,其实这是个非常有用的功能。
生成器和迭代器有点类似,但是与标准的PHP迭代器不同,PHP生成器不要求类实现Iterator接口,从而减轻了类的开销和负担。生成器会根据需求每次计算并产出需要迭代的值,这对应用的性能有很大的影响:试想假如标准的PHP迭代器经常在内存中执行迭代操作,这要预先计算出数据集,性能低下;如果要使用特定方式计算大量数据,如操作Excel表数据,对性能影响更甚。此时我们可以使用生成器,即时计算并产出后续值,不占用宝贵的内存空间。
2、创建生成器
生成器的创建方式很简单,因为生成器就是PHP函数,只不过要在函数中一次或多次使用yield关键字。与普通的PHP函数不同的是,生成器从不返回值,只产出值。下面是一个简单的生成器实现:
function getLaravelAcademy() {
yield 'http://LaravelAcademy.org';
yield 'Laravel学院';
yield 'Laravel Academy';
很简单吧!调用此生成器函数时,PHP会返回一个属于Generator类的对象,这个对象可以使用foreach函数迭代,每次迭代,PHP会要求Generator实例计算并提供下一个要迭代的值。生成器的优雅体现在每次产出一个值之后,生成器的内部状态都会停顿;向生成器请求下一个值时,内部状态又会恢复。生成器内部的状态会一直在停顿和恢复之间切换,直到抵达函数定义体的末尾或遇到空的return语句为止。我们可以使用下面的代码调用并迭代上面定义的生成器:
foreach(getLaravelAcademy() as $yieldedValue) {
echo $yieldedValue, PHP_EOL;
上面代码输出如下:
http://LaravelAcademy.org
Laravel学院
Laravel Academy
3、使用生成器
下面我们实现一个简单的函数用于生成一个范围内的数值,以此说明生成器是如何节省内存的。首先我们通过迭代器来实现:
function makeRange($length) {
$dataSet = [];
for ($i=0; $i<$length; $i++) {
$dataSet[] = $i;
return $dataSet;
$customRange = makeRange(1000000);
foreach ($customRange as $i) {
echo $i . PHP_EOL;
此时执行会报错,提示超出单个PHP进程内存限制(要为100万个数字提供内存空间):
下面我们来改进实现方案,使用生成器实现如下:
function makeRange($length) {
for ($i=0; $i<$length; $i++) {
yield $i;
foreach (makeRange(1000000) as $i) {
echo $i . PHP_EOL;
再次执行就可以毫无压力的打印出结果,因为生成器每次只需要为一个整数分配内存。
此外,一个常用的使用案例就是使用生成器迭代流资源(文件、音频等)。假设我们想要迭代一个大小为4GB的CSV文件,而虚拟私有服务器(VPS)只允许PHP使用1GB内存,因此不能把整个文件都加载到内存中,下面的代码展示了如何使用生成器完成这种操作:
function getRows($file) {
$handle = fopen($file, 'rb');
if ($handle == FALSE) {
throw new Exception();
while (feof($handle) === FALSE) {
yield fgetcsv($handle);
fclose($handle);
foreach (getRows($file) as $row) {
print_r($row);
上述示例一次只会为CSV文件中的一行分配内存,而不会把整个4GB的CSV文件都读取到内存中。
4、总结
生成器是功能多样性和简洁性之间的折中方案,生成器只是向前进的迭代器,这意味着不能使用生成器在数据集中执行后退、快进或查找操作,只能让生成器计算并产出下一个值。迭代大型数据集或数列时最适合使用生成器,因为这样占用的系统内存最少。生成器也能完成迭代器能完成的简单任务,而且使用的代码更少。
总而言之,生成器并没有为PHP添加新功能,不过使用生成器大大简化了某些任务,而且使用的内存更少,如果需要更多功能,例如在数据集中执行后退、快进以及查找功能,最好自己编写实现Iterator接口的类,或者使用PHP标准库(SPL)中某个原生的迭代器(http://php.net/manual/spl.iterators.php)。
PHP
内存
新特性
Iterator
Generator
生成器
迭代器
点赞
取消点赞
收藏
取消收藏
赞赏
分享到以下平台:
<< 上一篇:
现代 PHP 新特性系列(三) —— Trait 概览
>> 下一篇:
现代 PHP 新特性系列(五) —— 闭包和匿名函数
9 条评论
#1
杜新龙
评论于 6年前
正在删除评论...
学院君你好,本系列文章是否借鉴自《Modern PHP》? 请尊重知识版权
#2
学院君
评论于 6年前
正在删除评论...
确实 我在开头第一篇中声明了 以Modern PHP为蓝本 以Laravel源码为实例
#3
杜新龙
评论于 6年前
正在删除评论...
#4
幸福--简单
评论于 6年前
正在删除评论...
看起来上面这人心眼真小
#5
阿盖
评论于 6年前
回复 #37
正在删除评论...
学院君能给我们搭建这个平台,传播正能量!他是一个对社会有贡献的人!值得我们敬重!
#6
来来来
评论于 5年前
正在删除评论...
怎么看学院君说的生成器 貌似就是把一次大的查询分割成多次查询了 那我要查几万条数据 难不成一次查不出来就要查询几万次啊 数据库早崩了
#7
Charry Peng
评论于 3年前
正在删除评论...
小小纠错一下哦:第三点使用生成器那里,迭代csv文件里的:foreach ($getRows($file) as $row) { print_r($row); }$getRows($file)应该改成getRows($file)
#8
Senkrol
评论于 3年前
正在删除评论...
学院君大佬,我的基础打得不好,之前用了一本国内的php书籍误导了我好长时间。
最近才去买O`REILLY的经典实例和Modern PHP,但是总觉得基础没打全面,心里特别虚,恳请学院君给我一些建议,非常感谢
#9
学院君
评论于 3年前
回复 #8
正在删除评论...
多看多写多思考
登录后即可添加评论
升级为学院君订阅用户(新年优惠🎁)
内容导航
1、概述
2、创建生成器
3、使用生成器
4、总结
相关推荐
现代 PHP 新特性系列(一) —— 命名空间
现代 PHP 新特性与最佳实践
新特性
现代 PHP 新特性系列(三) —— Trait 概览
现代 PHP 新特性与最佳实践
新特性
现代 PHP 新特性系列(五) —— 闭包和匿名函数
现代 PHP 新特性与最佳实践
新特性
现代 PHP 新特性系列(七) —— 内置的 HTTP 服务器
现代 PHP 新特性与最佳实践
新特性
php.ini 配置调优 —— 让 PHP 应用性能维持在更高水平
现代 PHP 新特性与最佳实践
部署调优
回到顶部
2022 基于 Laravel 6 构建
关于学院
订阅服务
友情链接
站点地图
本站 CDN 加速服务由又拍云赞助