PHPのIterable型を使ってみる


TL;DR

  • PHPが用意してる型の1つのIterable型に関する内容
  • 特に、array型を受け取る前提、かつ、型に厳格さを求めるfunctionなどの場合、Iterable型での定義は最適な実装方法の1つではないかと感じる

前提

  • 実行環境
    • PHP 7.1.32

注意

Iterable は PHP 7.1 で導入された疑似型です。array、あるいは Traversable インターフェイスを実装したオブジェクトを 許容します。これらの型は、いずれも foreach で繰り返し可能であり、また、 ジェネレータ 内で yield from できます。

引用元:https://www.php.net/manual/ja/language.types.iterable.php

上記に記載されているように、公式ドキュメントには、Traversable インターフェイスを実装したオブジェクトも許容するとあるが、実際のユースケースとして、arrayの方が頻度は多いと判断したため、arrayを主に利用したサンプルコードと実際の挙動について触れてみる

20200128 追記

  • 以前記載したサンプルコードが適切ではなかったため、@picklesさんのご提示いただいたサンプルコードを引用させていただきます。非常に助かります。ありがとうございます。
<?php

function checkIterable(iterable $iterable): string
{
    return gettype($iterable);
}

var_dump(checkIterable(['apple', 'orange', 'banana']));

$type = new class implements iterator {
    private $position = 0;
    private $array = [
        'apple', 'orange', 'banana'
    ];

    public function __construct()
    {
        $this->position = 0;
    }

    /**
     * @inheritDoc
     */
    public function current(): string
    {
        return $this->array[$this->position];
    }

    /**
     * @inheritDoc
     */
    public function next(): void
    {
        ++$this->position;
    }

    /**
     * @inheritDoc
     */
    public function key(): int
    {
        return $this->position;
    }

    /**
     * @inheritDoc
     */
    public function valid(): bool
    {
        return isset($this->array[$this->position]);
    }

    /**
     * @inheritDoc
     */
    public function rewind(): void
    {
        $this->position = 0;
    }
};
var_dump(checkIterable($type));

$type = new class {};
var_dump(checkIterable($type));
  • 実行結果
% php iterable.php
string(5) "array"
string(6) "object"
PHP Fatal error:  Uncaught TypeError: Argument 1 passed to checkIterable() must be iterable, object given, called in /dev/iterable.php on line 64 and defined in /dev/iterable.php:3
...