blog.yuzu441.com

EloquentのDB::selectのレスポンスに対して型を定義する

tags: laravel php

注意

技術的に解決した話ではなくphpdocを書いて頑張る話です

他に良い方法があればこそっとX(旧 twitter)のDMか何かで教えて欲しい

概要

Laravelを使用した開発をしていて、DBへのアクセスをDB::selectなどでrawsqlを使用しているのでphpdoc無しだと、その返り値のプロパティに何があるかが分かりづらいので型定義したいと思って調べた

最初はarray{id: string}のように定義していたがDB::selectは連想配列ではなくstdClassが返ってくるようなのでdeclare(strict_types=1)が設定されている場合にエラーになってしまう。なのでobjectとして定義し@return object{id: string}というように書く必要がある

以下サンプル。今回の例はjoinしていないしUserクラスのようなものがあれば良さそうだが、実際のコードでは色々なテーブルをjoinしているので特定のクラスを定義するのが難しく、仮に用意するならXxxResultのようなものになるかと思う

<?php
declare(strict_types=1);

/**
 * @param $id user id
 * @return object{id:string,name:string}|null
 */
function getUser(string $id): object|null {
  $sql = "
  select
    id
    , name
  from
    users
  where
    id = :id
  limit
    1
  ;";

  return DB::selectOne($sql, ['id' => $id]);
}

$user = getUser();
$user?->name; // 補完も効いたし、name=stringというのも表示された

これがベストなのかはわからないが、一旦は補完と何型かわかるようになったので良し

余談

tscのような型検査が頑張ってくれる言語ばかり書いてきたのでphpのような言語でどこまでちゃんと書くのかでとても悩んでいる。厳密にphpdocを書いていくと労力が結構かかる気がしているんだけど、何かいい感じの解決方法があったりするのかとても気になる

動かさないと何が返ってくるかがわからなかったり、ドキュメントを見に行ってもmixedと書かれていて何が返ってくるのかコード確認するしか無さそうなのもなにか手はないものか…