🗓️

[PHP][GraphQL]12月32日を受け入れないようにする、とある1つのScalar

2021/05/02に公開

published_at: 2019-07-14


ちょっと試してみたところから、正しいってどこかな?と予想外に探したという小話です

環境

  • PHP 7.3
  • Laravel 5.8
  • Composer 1.8.6
  • nuwave/lighthouse 3.6.1
  • mll-lab/laravel-graphql-playground 1.0.2

こんなことが

年月日時分秒の時刻を示す文字列から、その「月末」を出す関数を実行した結果です


わざとあり得ない日時を渡したのですが、思わぬ方向に処理された、という感じです

正しくしようとして

ここでの「正しい」は、「間違ったものとして、処理させない」とします

カスタムScalarをつくる

公式[1]でも「実装次第」とかいているので、実装していきます


# php artisan lighthouse:scalar DateTime
Scalar created successfully.

# php artisan lighthouse:scalar Date
Scalar created successfully.

実装していったのがこちらになります

(そして、元から用意されてたのは使わないようにコメントアウト)


実装のポイント

何をもってこの年月日時分秒の時刻を示す文字列を「正しい」とするかを判定するメソッドを、自分はこのようにしました


    private function validate($target): bool
    {
        if (!\is_string($target)) {
            return false;
        }
        return $target === \date('Y-m-d H:i:s', \strtotime($target));
    }
  • 文字列じゃなかったらダメ
  • PHP標準の date 関数・strtotime 関数 で時刻オブジェクト化して文字列フォーマットにした結果が、
    元の年月日時分秒の時刻を示す文字列と完全一致してなかったらダメ

ここがミソ(と思っているところ)

  • 標準関数のみで実装
    • 便利な Carbon クラスを敢えて使っていない
  • 例外処理を利用することを避けている
    • 必要以上のことを積んで重くするレイヤーじゃないと思って

結果


間違ってるよ、とはじくようになりました 😎
一方で、正しいものを意図通りに結果を出すのもOK


まとめ(というか自分の結論)

  • ありがたく用意されているものでも、期待されている結果が得られるかを確かめたうえで使うのが良さそう
  • 何が「正しい」のかを考えるのは、とても良い頭の体操になる
  • 便利な高水準のオブジェクトを利用するシーン、プリミティブな比較的低水準の標準関数などを利用するシーンを適切に使い分けることができると楽しい

関連情報

そして


脚注
  1. https://graphql.org/learn/schema/#scalar-types ↩︎

Discussion