这篇文章主要介绍了关于PHP的多任务协程处理,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下
那么,开始吧!
这就是本文我们要讨论的问题。不过我们会从更简单更熟悉的示例开始。
一切从数组开始
我们可以通过简单的遍历来使用数组:
$array = ["foo", "bar", "baz"]; foreach ($array as $key => $value) { print "item: " . $key . "|" . $value . "\n";} for ($i = 0; $i < count($array); $i++) { print "item: " . $i . "|" . $array[$i] . "\n";}
这是我们日常编码所依赖的基本实现。可以通过遍历数组获取每个元素的键名和键值。
当然,如果我们希望能够知道在何时可以使用数组。PHP 提供了一个方便的内置函数:
print is_array($array) ? "yes" : "no"; // yes
类数组处理
有时,我们需要对一些数据使用相同的方式进行遍历处理,但它们并非数组类型。比如对 DOMDocument 类进行处理:
$document = new DOMDocument();$document->loadXML("<p></p>");$elements = $document->getElementsByTagName("p");print_r($elements); // DOMNodeList Object ( [length] => 1 )
这显然不是一个数组,但是它有一个 length 属性。我们能像遍历数组一样,对其进行遍历么?我们可以判断它是否实现了下面这个特殊的接口:
print ($elements instanceof Traversable) ? "yes" : "no"; // yes
这真的太有用了。它不会导致我们在遍历非可遍历数据时触发错误。我们仅需在处理前进行检测即可。
不过,这会引发另外一个问题:我们能否让自定义类也拥有这个功能呢?回答是肯定的!第一个实现方法类似如下:
class MyTraversable implements Traversable{ // 在这里编码...}
如果我们执行这个类,我们将看到一个错误信息:
PHP Fatal error: Class MyTraversable must implement interface Traversable as part of either Iterator or IteratorAggregate
Iterato本文来源gao@daima#com搞(%代@#码@网&搞gaodaima代码r(迭代器)
我们无法直接实现 Traversable,但是我们可以尝试第二种方案:
class MyTraversable implements Iterator{ // 在这里编码...}
这个接口需要我们实现 5 个方法。让我们完善我们的迭代器:
class MyTraversable implements Iterator{ protected $data; protected $index = 0; public function __construct($data) { $this->data = $data; } public function current() { return $this->data[$this->index]; } public function next() { return $this->data[$this->index++]; } public function key() { return $this->index; } public function rewind() { $this->index = 0; } public function valid() { return $this->index < count($this->data); }}
这边我们需要注意几个事项:
-
我们需要存储构造器方法传入的 $data 数组,以便后续我们可以从中获取它的元素。
-
还需要一个内部索引(或指针)来跟踪 current 或 next 元素。
-
rewind() 仅仅重置 index 属性,这样 current() 和 next() 才能正常工作。
-