はじめまして。
今月からRoxxな人になった前田といいます。
よろしくおねがいします。
PHPでは...というキーワードがあります。
以下、例です。
<?php // 可変長引数 function printArgs(...$inputs) { echo $inputs[0]; // apple echo $inputs[1]; // banana echo $inputs[2]; // chocolate } printArgs('apple', 'banana', 'chocolate');
<?php // 引数のアンパック function printArgs($a, $b, $c) { // 略 } $args = ['aaple', 'banana', 'chocolate']; printArgs(...$args);
前から存在は知っていたのですが、わりと自分の中ではただのトリビアになっていて、あまり使用してきませんでした。
というより使用する場面をいまいち把握できていませんでした。
最近、個人で開発しているときに「あれ、意外と...は便利なのでは!?」となったので紹介します。
事例
以下の仕様のクラスを考えます。
- ユーザ定義クラスStatusがある
- Statusを複数まとめて扱うクラスがほしい
- つまり、配列をラップしたクラス
- 以下の要件を備える
...をつかわない場合
以下のようになると思います。
<?php class StatusCollection { /** @var Status[] */ private $items; public function __construct(array $items) { foreach ($items as $item) { if (!$item instanceof Status) { throw new InvalidArgumentException(); } } $this->items = array_values($items); } } $items = [Status::on(), Statuss::off(), Status::unknown()]; $statuses = new StatusCollection($items);
ポイントとしては、Status以外の要素がある場合は例外を投げていること、 array_values でキーを振り直しているところです。
こういったバリデーションに近い部分にコードを多く使うと読みづらいですね。
こういった読みづらさを...を使うと解消できます。
array_valuesを取り除く
まず array_values を消していきます。
<?php class StatusCollection { /** @var Status[] */ private $items; public function __construct(...$items) { foreach ($items as $item) { if (!$item instanceof Status) { throw new InvalidArgumentException(); } } $this->items = $items; } } $items = [Status::on(), Statuss::off(), Status::unknown()]; $statuses = new StatusCollection(...$items);
コンストラクタの仮引数を ... に変更しました。
これにより、キーの採番はPHPが勝手に行うようになるので、array_valuesが不要になります。
また、仮引数を可変長引数にしたので、実引数も忘れずに...でアンパックします。
型チェックのコードを取り除く
次に一番面積をとっているforeachを消していきます。
<?php class StatusCollection { /** @var Status[] */ private $items; public function __construct(Status ...$items) { $this->items = $items; } } $items = [Status::on(), Statuss::off(), Status::unknown()]; $statuses = new StatusCollection(...$items);
単純に型宣言(タイプヒント)を使用しています。
...を使う前は配列を受け取っていたのでarrayで指定していましたが、...を使うことで配列の要素の型を指定できます。
面積をとっていたforeachを削除できたので、とても見通しの良いコードになりました。
まとめ
...を使用することで、配列のキーを気にしなくて済む...を使用することで、配列の要素の型を指定できる
...は型宣言とセットで使用することでパワーを発揮しそうです。
「連想配列じゃなくてもいいんだけど・・・」という場合も結構あるので、配列のキーを気にしなくて良い場合は積極的に使っていこうと思います。