LaravelのCollectionクラスのような、foreach
可能なオブジェクトを作ります。
実装の幅が広がるので覚えておいて損はないです。
環境
- PHP 8.0.1
前提知識: IteratorAggregate
コレクションクラス(イテレート可能なオブジェクト)を作成するためにはPHPが用意している IteratorAggregate
インターフェースを契約する必要があります。
https://www.php.net/manual/ja/class.iteratoraggregate.php
IteratorAggregate extends Traversable {
abstract public getIterator(): Traversable
}
Let's try!
- Task.php (入れ物に入れる物)
- TaskList.php (入れ物)
- main.php (お試し実行用のファイル)
3つのファイルを作ります。
Task.php
何でもいいのですが、例としてTask
クラスを作ります。
<?php
declare(strict_types=1);
final class Task
{
public function __construct(private int $id)
{
}
public function name(): string
{
return 'task' . $this->id;
}
}
TaskList.php
Taskクラスを格納するTaskListコレクションクラスを実装します。
<?php
declare(strict_types=1);
/**
* @implements IteratorAggregate<int, Task>
*/
final class TaskList implements IteratorAggregate
{
public function __construct(private array $attributes = [])
{
}
public function getIterator(): ArrayIterator
{
return new ArrayIterator($this->attributes);
}
}
コレクションとなるクラスは getIterator()
メソッドを実装していればokです。
main.php
<?php
declare(strict_types=1);
require('./Task.php');
require('./TaskList.php');
$taskList = new TaskList([
new Task(1),
new Task(2),
new Task(3),
new Task(4),
new Task(5),
]);
foreach ($taskList as $task) {
echo $task->name() . PHP_EOL;
}
main.php
を実行してみます。
$ php main.php
task1
task2
task3
task4
task5
TaskList
クラスをforeach
で回してTaskクラスのインスタンスを取得してname()
メソッドを実行できました。
補足: add(), count()
add()
, count()
を追加するとより便利に使えます。
Countable
インターフェースを契約してcount()
メソッドを実装するとより良いです。
<?php
declare(strict_types=1);
/**
* @implements IteratorAggregate<int, Task>
*/
final class TaskList implements IteratorAggregate, Countable
{
public function __construct(private array $attributes = [])
{
}
public function getIterator(): ArrayIterator
{
return new ArrayIterator($this->attributes);
}
public function add(Task $task): void
{
$this->attributes[] = $task;
}
public function count(): int
{
return count($this->attributes);
}
}
add(Task $task)
メソッドでは型宣言しているので、配列追加時にTaskのインスタンスを安心して追加できます。
<?php declare(strict_types=1);
require('./Task.php');
require('./TaskList.php');
$taskList = new TaskList();
$taskList->add(new Task(1));
$taskList->add(new Task(2));
$taskList->add(new Task(3));
echo $taskList->count() . PHP_EOL;
echo count($taskList) . PHP_EOL;
Countable
インターフェースを実装したクラスはcount($taskList)
とcount()
関数を使用できます。
$ php main.php
3
3