【Laravel】ScribeでAPIドキュメントを作成

Laravel Advent Calendar 2022 9日目の記事です。
Laravel+ScribeでAPIドキュメントを作成する方法をまとめました。

https://qiita.com/advent-calendar/2022/laravel

## はじめに
小規模ですが、フロント・バックエンドのチームに分かれて開発をしています。
フロント側の人から「APIの仕様がまとまっていたら助かる」という声をもらい、APIのドキュメントについて調べたところ、今回のScribeを見つけ実装しました。
本記事では、途中つまったところに重点を置いてまとめます。
## 環境
* PHP 8.1.5
* Laravel 9
* Laravel Sail
## 使用したライブラリ
https://scribe.knuckles.wtf/
## 実装手順
こちらの記事に分かりやすく書かれてましたので、参考にさせていただきました。
こちらをご参照ください。

https://aimstogeek.hatenablog.com/entry/2021/07/19/080000#Scribe%E3%81%A8%E3%81%AF

## つまり① : 認証
APIドキュメントのページを生成できましたが、APIを叩くには認証済みになってないといけません。
最初どうやって認証するのか迷いましたが、シンプルにログインをすればOKでした。  

---
##### 1. DBにあるメールアドレス・パスワードでログイン 
![Monosnap back-local Documentation 2022-12-08 20-30-49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2016468/68d0f320-a06b-98f7-cda2-64e4352818af.png)
##### 2. CSRFトークンを取得
Laravel Sanctumを使って認証機能を実装しています。
以下の操作でCSRFトークンを取得します。
![Monosnap back-local Documentation 2022-12-08 20-38-30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2016468/96741476-8208-289d-00cb-dd1c39003e9a.png)

ここまでの操作で認証完了です。
実際にAPIを叩いてレスポンスを確認することができます。
## つまり② : SANCTUM_STATEFUL_DOMAINSの設定（SPAの場合）
結果単純なことでしたが、ここで結構つまりました。
##### 前提①
envファイル内の`SANCTUM_STATEFUL_DOMAINS`と`srcibe.php`内の`base_url`が一致していないと、Scribeで生成したAPIドキュメントで認証を通すことができないようです。
##### 前提②
我々は、**バックエンド：Laravel・フロントエンド：React, Next.js**でSPA開発をしています。
Santcumの認証を通すドメインを指定する`SANCTUM_STATEFUL_DOMAINS`には フロント側のURLのドメイン`例：localhost:3000`を指定しています。
##### 起こったこと
`Srcibe.php`内の`base_url`を`SANCTUM_STATEFUL_DOMAINS`に合わせて、`http://localhost:3000`としてAPIドキュメントを生成しました。
SailでAPIドキュメントを生成する時は`sail artisan scribe:generate`　です。
そうすると、`404エラー`のページになってしまいます。
![Monosnap Making a custom 404 page in Next.js 2022-12-08 21-08-59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2016468/34353ce9-a9d0-2eb5-3715-516a30b4e29c.png)
これは単純で、Next.jsで`/docs`のページが存在しないため出てしまいます。
##### 解決した方法
Next側で`/docs`のURLだけビルドさせないようにするか？など解決策を考えましたが、結果Laravel側で`SANCTUM_STATEFUL_DOMAINS`に複数のドメインを設定するだけでOKでした。`srcibe.php`の設定も変える必要はありません。
ドメインを1つしか設定できないと思い込んでしまっていて、ここまでに時間がかかってしまった。。
こんな感じです。
```php:.env
SANCTUM_STATEFUL_DOMAINS=localhost:3000,localhost
```
## つまり③ : パラメータの渡し方
##### 起こったこと
GETのAPIを叩こうとすると、クエリパラメータとボディパラメータの２箇所で、同じパラメータの入力欄が出てします。実際にパラメータとして送りたいのは、`status(int型)`1つだけ。同じ値を２箇所に入れても、片方だけ空欄のまま実行しても、エラーになってします。
![Monosnap back-local Documentation 2022-12-08 21-29-32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2016468/5dbff284-eb7f-f2ba-b0db-b985b07d47b4.png)
色々調べてみると、`FormRequest`が関係してるようでした。`FormRequest`を利用すると、意図せず２つのパラメータ入力欄が出てしまうことがあるらしいです。今回、ほぼ全てのAPIで`FormRequest`をカスタマイズしたものをバリデーションとして使っているので、おそらくそれが原因でした。
##### 解決した方法
使用しているカスタム`FormRequest`のファイルに、以下の記述をして解決できました。
この記述をしてAPIドキュメントを生成すると、クエリパラメータ入力欄のみ表示されました。値を入力して実行すると、あるべきレスポンスを返すことができました。
```php:カスタムFormRequest
/**
 * Query parameters
 * You can still have other stuff in your docblock.
 */
class CreatePostRequest extends FormRequest
{
```
この解決策については、公式のドキュメントにしっかり書いてありました。

https://scribe.knuckles.wtf/laravel/documenting/query-body-parameters#using-validation-rules-for-query-parameters

## 最後に
今回APIドキュメントを作ったことによって、必要なパラメータを確認したり、実際に叩いてレスポンス内容を確認することができるので、バックエンド・フロントエンド分かれてチーム開発する上で非常に重要だと感じました。また、バックエンド側の負担も少なくしたいので、今回のscribeのようにアノテーションを書くだけでドキュメントを作成できるのは便利でした。より利便性を高めるためには、Swaggerとの連携もできるようなので、今後試してみたいと思います。
## 参考
https://scribe.knuckles.wtf/

https://aimstogeek.hatenablog.com/entry/2021/07/19/080000#Scribe%E3%81%A8%E3%81%AF

https://rarejob-tech-dept.hatenablog.com/entry/2022/03/04/190000#Scribe%E3%81%AE%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95

https://marble-heroes.com/blog/idwlqq3z9gr