31
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PHP 自作のコレクション(リスト)クラスを実装する

Last updated at Posted at 2021-02-10

LaravelCollectionクラスのような、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クラスを作ります。

Task.php
<?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コレクションクラスを実装します。

TaskList.php
<?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

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のインスタンスを安心して追加できます。

main.php
<?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

参考

31
23
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?