当前位置:首页 > 文章列表 > 文章 > php教程 > PHP Generator return 获取遍历结束值的实现方式

PHP Generator return 获取遍历结束值的实现方式

来源:17golang原创 2026-11-13 16:31:12 0浏览 收藏

PHP 生成器的遍历结束值,要在同一个 Generator 正常执行完毕后调用 getReturn()取得。yield提供 foreach 消费的逐项数据,return提供生成器结束时的独立结果;它不会变成 foreach 的最后一项。若提前 break 或执行因未处理异常中断,就不能把循环外的位置当成“汇总已经准备好”。

PHP 官方手册:https://www.php.net/manual/en/generator.getreturn.php

先保留 Generator,再在完整遍历后取汇总

例如价格流需要一边输出条目,一边在结束后给出条数和总额,可以把明细放在 yield,把汇总放在 return。下面是原创 PHP 8 示例,展示预期语义,未作为本机运行记录。

 $count, 'total' => $total];
}

// 保存这一次调用返回的对象,避免结束后又创建一个新生成器。
$rows = pricedRows([12, 25, 8]);
foreach ($rows as $price) {
    echo $price, PHP_EOL;
}
// 完整消费后读取汇总;return 数组不会成为 foreach 的额外一项。
$summary = $rows->getReturn();
echo json_encode($summary, JSON_UNESCAPED_UNICODE), PHP_EOL;

按这段代码,明细依次为 12、25、8;结束汇总是 {"count":3,"total":45}。这两个通道用途不同:消费者可逐项处理,最后再读取一个小型结果,无需为了取得汇总而先把整个明细流转成数组。

调试时首先看变量是否指向同一对象。pricedRows(...)每调用一次都会得到一个新的生成器;遍历一个对象以后,再调用函数并在新对象上取返回值,读不到先前那次遍历的结果。函数签名中的 : Generator描述函数交给调用方的对象类型,不是在声明内部 return 数组的类型。

Generator对象与yield明细return汇总及消费者的静态关系
原创结构图:同一个生成器关联两种结果。foreach读取yield明细,结束后的getReturn读取return汇总,不是运行截图。

拿不到返回值时,检查是否仍停在 yield

getReturn() 是读取接口,不会替调用方把剩余任务自动执行完。刚创建生成器、停在中间某个 yield、甚至停在最后一个 yield,都可能尚未执行到最终 return。普通 foreach 完整结束会继续推进到结束;在循环体中 break 则不会完成这件事。

 1];
}

$items = stockItems();
foreach ($items as $item) {
    // break 只停止消费者循环,生成器此时仍暂停在 yield。
    break;
}
// 此例中 valid() 为 true,不调用 getReturn(),也不擅自继续消耗。
if ($items->valid()) {
    echo '当前只有部分数据,尚无结束汇总', PHP_EOL;
}

这个例子尤其容易误判:只有一个 yield,消费者也已经拿到那一项,但 return 在恢复执行之后才会到达。若业务确实要处理完整输入,应按原消费逻辑继续;若业务就是找到首项即停止,应把结果定义为部分结果,不应为了取汇总盲目调用 next() 排空生成器,因为剩余代码可能还包含读取、计算或写入等副作用。

手动遍历还应区分 current() 和 next():前者用于取当前明细,后者恢复生成器。next() 没有“返回最终汇总”的职责。使用何种遍历方式,都要把消费动作与完成结果的读取分别写清。

用 yield from 时显式接住内部返回值

外层使用 yield from 委托内部生成器时,内部 yield 的条目会向外暴露,内部 return 则是 yield from 表达式的值。若外层需要向调用方报告该汇总,必须显式接住并 return,或者将其包装进外层结果。

 2];
}

function exportValues(): Generator
{
    // yield from 转交明细,其表达式结果是内部生成器的 return 值。
    $innerSummary = yield from chunkValues();
    return ['source' => 'demo', 'summary' => $innerSummary];
}

$export = exportValues();
foreach ($export as $value) {
    echo $value, PHP_EOL;
}
// 读取的是外层明确返回的结构,不会自动跳到内部生成器。
var_export($export->getReturn());

此例最终结果含有外层的 source 和内部 summary。假如外层仅写 yield from chunkValues(); 然后自然结束,没有返回该表达式结果,调用外层 getReturn() 不会自动替你找到内部汇总。若只想原样转交,可以写 return yield from chunkValues();。

内部生成器yield from表达式内部汇总外层生成器与外层getReturn的关系
原创结构图:内部汇总属于yield from表达式结果,外层return决定调用方最终读取的结构;图中连线表达归属,不表示执行时序。

委托也可以面向数组等可遍历对象,但不要因此假定所有 iterable 都具有生成器式结束汇总。接口若依赖 getReturn(),就应明确要求 Generator,或在边界处做相应类型处理。语法依据:https://www.php.net/manual/en/language.generators.syntax.php。

把正常完成与中断分成不同处理分支

完整遍历且正常返回时,再读取汇总;业务提前结束时,记录部分处理状态;异常逃出生成器或消费者时,先按失败路径处理。不能在 catch 中不加区分地调用 getReturn() 来“补取成功结果”,也不宜用 finally 无条件读取汇总,以免读取错误掩盖原始异常。

还要区分“无法读取返回值”和“返回值本来是 null”。生成器正常走到末尾但没有显式返回结果时,结束值可为 null;显式 return null;也同样如此。不要用 if ($gen->getReturn())判断是否完成,因为 0、false、空数组和 null 都可能是合法结束值。

valid() 可以帮助识别是否仍有当前迭代项,但它不是业务成功标识;初始化尚未启动的生成器时也可能推进执行。即使生成器已不再有效,若其执行是因异常终止,也不能直接推断一定存在正常结束汇总。工程上应由消费流程保留正常完成与失败状态,而不是仅根据一个布尔值恢复业务结论。

按症状选择需要修改的位置

症状优先检查修改方向
foreach 没有出现汇总是否把 return 当作 yield循环结束后对原对象调用 getReturn()
提示尚未返回是否刚创建、提前 break 或停在最后一个 yield明确完整消费或部分结果的契约
明细正常,结果为 null是否正常结束但没有 return 汇总显式 return 所需结构
内部返回了,外层没取到yield from 表达式结果是否丢弃保存内部汇总并显式返回
统计与实际成功数不一致统计的是产出数还是消费成功数分别定义和记录两种计数

读代码时,可以按“原对象、完成时机、return 所在层、失败分支”四个位置检查。示例中的 count 是生成器产出的数量;如果消费者收到条目后写数据库失败,生成器不会自动知道写入是否成功。跨越两个组件的业务统计应单独建模。

常见问题

getReturn() 支持哪些 PHP 版本?

官方手册将该方法列为 PHP 7、PHP 8 功能。本文示例按 PHP 8 写法展示。

iterator_to_array() 能把结束汇总一并放进去吗?

它收集的是迭代项,return 不会成为额外明细。保留 Generator 对象,在完整消费后另取汇总;无须收集全部明细时,直接 foreach 更合适。

break 后还想随时看到统计怎么办?

应另行设计进度状态或消费者计数。结束汇总以正常完成为前提,不能承担实时进度接口的职责。

需要 new Generator() 吗?

不需要,也不能这样实例化。调用包含 yield 的生成器函数即可取得 Generator 对象。类手册:https://www.php.net/manual/en/class.generator.php。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
PHP PDO 禁用模拟预处理后的参数类型边界PHP PDO 禁用模拟预处理后的参数类型边界
上一篇
PHP PDO 禁用模拟预处理后的参数类型边界
PHP 8.5 partitioned Cookie 参数的兼容配置清单
下一篇
PHP 8.5 partitioned Cookie 参数的兼容配置清单
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    1012次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    1017次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1142次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1115次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    959次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码