LoginSignup
5
2

More than 3 years have passed since last update.

PHPでOption型を利用してnullチェックや例外ハンドラを消す

Posted at

ScalaやRustを普段使ってる方には当たり前にあるOption型ですが、残念ながらPHPには組み込みされていません。
しかし、php-optionを利用することで同様の体験を得ることが出来ます。
https://github.com/schmittjoh/php-option

こんなコード書いてませんか?

例外を投げる

例えばRepositoryからEntityを取得する処理でこんなコードを書いてませんか?

Repository
public function findById(Id $id): Entity
{
  $result = $this->queryBuilder->...
  if ($result === null) {
    throw New NotFoundException('message');
  }
  return Entity::create($result);
}

データベースからデータを取得して、データがなければ例外、あればEntityとして返却するというコードを書いたことがある人もいるかと思います。
しかし、この関数を利用する際に適切に例外ハンドラを作らないと意図しないエラー画面を出力してしまう可能性があります。

is_nullで値の確認

こんな処理も書いていないでしょうか?

$hoge = $entity->getHoge();
if (is_null($hoge)) {
    return; // デフォルトで返したい値など
}
return $hoge;

とあるEntityから取得できるValueObject等がnullableの場合にis_nullなどを利用してチェックする処理などを書いていないでしょうか?
また、このようなチェックを見逃して意図しない値をViewに渡してしまうなどしてないでしょうか?

値がある型、値がない型に分ける

Some型とNone型という、なにか値のある型と値がない型に分けることで処理をわかりやすくします。

先程のRepositoryでのコードを例に書き換えてみます。

Repository
public function findById(Id $id): Option
{
  $result = $this->queryBuilder->...
  if ($result === null) {
    return None::create();
  }
  return Some::create(Entity::create($result));
}

結果がnullだった場合はNone型、値があればSome型として返却します。
このOption型をどう使うかは次のis_nullチェックしていた例を見てみます。

$hoge = $entity->getHoge();
return $hoge->getOrElse('デフォルトで返したい値など');

getHoge()がRepositoryの例のようにOption型が返ってくると想定しています。Option型にはgetOrElseというメソッドがあり、値があれば取得できて値がなければ引数で指定した値を返すという関数です。

また、値があることだけを確認したい場合も

$hoge = $entity->getHoge();
if ($hoge->isEmpty()) {
  // None型
}
if ($hoge->isDefined()) {
  // Some型
}

このようにメソッドが用意されているので簡単に分岐を作ることが出来ます。

まとめ

Option型を使うことで明示的に値があるかもしれないし、無いかもしれないという型を作ってその振る舞いを扱いやすくできました。
ちなみにphp-optionはphpdotenvで利用されていて知りました。
env('KEY', {default})はまさに値があるかもしれないし、無いかもしれないものですよね。

小言

PhanとかPHPStanを使えばコメントでジェネリクスを表現してIDEでサポートされたりするんでしょうか?(知らない)
ジェネリクスを書きたい、Hackを書くしか無いか・・・

5
2
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
5
2