【Laravel】フォームリクエストから API ドキュメントに使いやすいリクエスト部の説明を作る

 Laravel は PHP フレームワークであり多くの場合、 web サイトの作成で使われます。Laravel にはクライアントからのリクエストを制御する機能が多く備わっておりフォームリクエストはその一つです。
バリデーション 6.x Laravel#フォームリクエストバリデーション
 フォームリクエストは次の様に使うとリクエストの内容を自動でバリデーションしてくれます。

class PostStoreRequest extends FormRequest
{
	public function rules()
	{
	    return [
	        'title' => 'required|unique:posts|max:255',
	        'body' => 'required',
	    ];
	}
}

class PostController extends Controller
{

    public store(PostStoreRequest $request)
    {
        // 引数の型を元にリクエストがPostStoreRequestインスタンスになり、バリデーションが自動で走ります。
        // バリデーションエラーがない場合のみ本処理に入ります。
    }
}

 フォームリクエストはリクエストの内容を表現するクラスであり API ドキュメントを作る時はフォームリクエストの中身について表現するのがほとんどです。フォームリクエストクラスに API ドキュメント用のテキストを出力したくなります。これは次で行うと便利です。

<?php

namespace App\Http\Requests;

use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Arr;

abstract class BaseFormRequest extends FormRequest
{
    abstract public function rules(): array;

    /**
     * ルールについての説明文字列の配列を返します
     * @return array<string>
     */
    public function getRuleDescriptionList(): array
    {
        $returnStringList = [];

        foreach ($this->rules() as $name => $rule) {
            if (is_string($rule)) {
                // 'required|string'の様な文字列定義のルール⇒ ${ルールのラベル}: ルール定義
                $returnStringList[$name] = implode(': ', [$this->getAttribute($name), $rule]);
                continue;
            }
            // ['required', 'string', new Exists()]の様な配列定義のルールならば
            // ${ルールのラベル}: ルールの配列を','で結合
            $returnStringList[$name] = implode(': ', [
                $this->getAttribute($name),
                collect($rule)->map(static function ($r) {
                    if (is_string($r)) {
                        return $r;
                    }

                    // もしルールがインスタンスならば文字列表現があるならそれ、なければクラス名の文字列に変換
                    if (method_exists($r, '__toString')) {
                        return $r->__toString();
                    }

                    return class_basename($r);
                })->join(', ')
            ]);
        }

        return $returnStringList;
    }

    /** リクエストのキーについてのラベルを取得 */
    protected function getAttribute(string $key): string
    {
        return $this->attributes()[$key] ?? $key;
    }

    /** リクエストのキーについての説明を取得 */
    public function getRuleDescription(string $key): string
    {
        return $this->getRuleDescriptionList()[$key] ?? '';
    }
}

 この BaseFormRequest クラスを継承して次の様なフォームリクエストクラスを作ると

class PostStoreRequest extends BaseFormRequest
{
	public function rules(): array
	{
	    return [
	        'title' => ['required','unique:posts','max:255'],
	        'phoneNumber' => ['required', new PhoneNumber],
	    ];
	}
	
	public function attributes()
	{
	    return [
	        'title' => '題名',
	        'phoneNumber' => '携帯電話番号',
	    ];
	}
}

class PhoneNumber implements Rule
{
    // 電話番号のバリデーション
    
    /**
     * 文字列化する時に呼ばれる処理 
     * @see https://www.php.net/manual/ja/language.oop5.magic.php#object.tostring
     */
    public function __toString()
    {
        return '電話番号';
    }
}

 次の様にインスタンスからメソッドを呼ぶだけでいい感じのリクエストのキーと説明用の文字列を作れます。

$request = new PostStoreRequest();
echo json_encode($request->getRuleDescriptionList(),JSON_PRETTY_PRINT);

/*
{
  "title": "題名: required,unique:posts,max:255",
  "phoneNumber": "携帯電話番号: required,電話番号"
}
*/

 こういったものと API ドキュメント用の便利ソフト(次図は API Documentation & Design Tools for Teams | Swaggerを使いました)を利用すると次の様な web ページを出力する API ドキュメントも自動生成できます。

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG