PHP 简明教程

PHP 可迭代对象

1. 什么是可迭代对象 (Iterable)?

iterable 是 PHP 7.1 引入的一种伪类型(pseudo-type)。它接受任何可以被 foreach 循环遍历的值。

既然一个变量可以被循环,那么它就符合 iterable 的定义。这在函数参数或返回值中非常有用,因为它允许函数同时接受数组和实现了 Iterator 接口的对象,而无需分别定义不同的类型约束。

2. 使用 Iterable 作为参数

函数可以接受一个可迭代对象作为参数。任何数组或实现了 Iterator 接口的对象都可以传入该参数。

代码示例:

<?php
function printIterable(iterable $myIterable) {
  foreach($myIterable as $item) {
    echo $item;
  }
}

$arr = ["a", "b", "c"];
printIterable($arr);
?>

3. 使用 Iterable 作为返回值

函数也可以返回一个可迭代对象。这告诉调用者,返回的结果可以被 foreach 遍历。

代码示例:

<?php
function getIterable(): iterable {
  return ["a", "b", "c"];
}

$myIterable = getIterable();
foreach($myIterable as $item) {
  echo $item;
}
?>

4. 创建可迭代对象

数组和实现了 Iterator 接口的对象都被视为 iterable

4.1 数组 (Arrays)

所有的数组都是可迭代的,因此它们可以传递给任何要求 iterable 类型的函数。

4.2 迭代器 (Iterators)

任何实现了 Iterator 接口的对象都可以作为可迭代对象使用。迭代器包含一个记录在列表中位置的指针,以及用于在列表中导航的方法。

如果您的数据模型过于复杂,无法用简单的数组表示,但您仍希望能够使用 foreach 遍历它,那么实现 Iterator 接口是最佳解决方案。

5. Iterator 接口详解

要实现 Iterator 接口,类必须包含以下五个方法,以便 foreach 循环能够正确执行:

  • current() - 返回当前指针指向的元素。它可以是任何数据类型。
  • key() - 返回与列表中当前元素关联的键(Key)。
  • next() - 将指针移动到列表中的下一个元素。
  • rewind() - 将指针重置到列表的开头。
  • valid() - 如果指针当前指向的元素存在,则返回 true,否则返回 false(循环在此终止)。

5.1 实战示例:自定义迭代器

下例展示了如何实现 Iterator 接口并创建一个可迭代对象:

代码示例:

<?php
// 创建一个迭代器类
class MyIterator implements Iterator {
  private $items = [];
  private $pointer = 0;

  public function __construct($items) {
    // array_values 确保数组具有数字索引
    $this->items = array_values($items);
  }

  public function current() {
    return $this->items[$this->pointer];
  }

  public function key() {
    return $this->pointer;
  }

  public function next() {
    $this->pointer++;
  }

  public function rewind() {
    $this->pointer = 0;
  }

  public function valid() {
    // 检查指针位置是否存在对应的元素
    return $this->pointer < count($this->items);
  }
}

// 使用该迭代器
$myIter = new MyIterator(["苹果", "香蕉", "樱桃"]);

foreach($myIter as $key => $value) {
  echo "$key: $value <br>";
}
?>

开发建议: 使用 iterable 类型提示可以显著增强代码的通用性。例如,在编写数据导出函数时,声明接受 iterable 参数,意味着该函数既可以处理现成的数组,也可以处理从数据库中逐条获取数据的生成器(Generator)或迭代器对象,从而有效控制内存占用。