swagger-php で書く Annotation テンプレ3種

この記事は、温かみのある手作業で swagger-php の annotation を書かなければいけない人向けに、コピペで使えるannotationを提供する目的でまとめます。


# 単なる key value 表現のannotation

#### 出力例

```
{
  "id": "1",
  "name": "サンプル太郎",
  "email": "example@hoge.com",
  "created_at": "2006-04-13T14:12:53+09:00"
}
```

#### annotation

```
    /**
     * @OA\Get(
     *   tags={"Common"},
     *   path="/api/user",
     *   @OA\Response(
     *       response="200",
     *       description="success",
     *       @OA\JsonContent(ref="#/components/schemas/user_responder")
     *   ),
     *   @OA\Response(
     *       response="204",
     *       description="there is no authorized user",
     *       @OA\JsonContent(ref="#/components/schemas/204_no_content")
     *   )
     * )
     */
```

tags は swagger-ui で見るときに整理されて見えるので便利のためにつけてます。
Response については別のところで定義した schema を参照するようにして、リクエストとレスポンスを別々に定義できるようにしています。

以下は schema の書き方です。
まずはシンプルな方式から。

```
/**
 * @OA\Schema(
 *   schema="user_responder",
 *   required={"id", "name", "email", "created_at"},
 *   @OA\Property(
 *     property="id",
 *     type="integer",
 *     description="ユーザID",
 *     example="1"
 *   ),
 *   @OA\Property(
 *     property="name",
 *     type="string",
 *     description="ユーザの名前",
 *     example="サンプル太郎"
 *   ),
 *   ~その他フィールド略。追加する場合にはカンマを忘れがちなのでお気をつけて~
 * )
 */

```

クラスやフィールドに寄り添った書き方。分解して書くことができます。

```
/**
 * @OA\Schema(
 *   schema="user_responder",
 *   required={"id", "name"}
 * )
 */
class UserResponder extends BaseResponder
{
    /**
     * @OA\Property(
     *     property="id",
     *     type="integer",
     *     description="ユーザID",
     *     example="1"
     * ),
     */
    private $id;

    /**
     * @OA\Property(
     *     property="name",
     *     type="string",
     *     description="ユーザの名前",
     *     example="サンプル太郎"
     * ),
     */
    private $name;

```

required はそれぞれのプロパティに書くのではなくて、schemaに定義します。



# 配列を含むannotation

#### 出力例

```
{
  "news": [
    {
      "id": 5,
      "title": "Synergy Night Fever 2019 ──国内ベンチャーシーンを牽引する経営者3名とM&Aについて語る イベントレポート",
      "created_at": "2019-08-26T11:01:38+09:00"
    },
    {
      "id": 4,
      "title": "テスト",
      "created_at": "2019-07-31T10:41:21+09:00"
    },
  ]
}
```

#### annotation 

```    
    /**
     * @OA\Get(
     *   tags={"Media"},
     *   path="/api/news",
     *   @OA\Response(
     *       response="200",
     *       description="success",
     *       @OA\JsonContent(ref="#/components/schemas/news_list_responder")
     *   ),
     * )
     */
```

呼び出される schema は以下のようになります。

```
/**
 * @OA\Schema(
 *     schema="news_summary",
 *     required={"id", "title", "created_at"},
 *     @OA\Property(property="id", type="integer", example=1),
 *     @OA\Property(property="title", type="string", example="タイトル"),
 *     @OA\Property(property="created_at", type="string", example="2020-01-17T11:25:28+09:00"),
 * )
 */
/**
 * @OA\Schema(
 *   schema="news_list_responder",
 * )
 */
class NewsListResponder extends BaseResponder
{
    /**
     * @OA\Property(
     *     property="news",
     *     type="array",
     *     @OA\Items(
     *       ref="#/components/schemas/news_summary"
     *     ),
     * )
     */
    private $news;
```

ちょっと複雑ですが、要するに、まずは `list` の schema を呼び出して、property が配列なので、さらに別のschemaを呼び出しています。
array type の property の中で schema を定義せず全て子供の property を定義することも試したのですが、それは動きませんでした。ちょっとハマりどころ。


# キーに対してオブジェクトを指定するannotation

#### 出力例

```
{
  "number_of_people_options": {
    "1": "~5人",
    "2": "5~10人"
  },
  "headquarter_location_options": {
    "1": "北海道",
    "2": "青森県"
  }
}
```

#### annotation 

```
    /**
     * @OA\Get(
     *   tags={"Common"},
     *   path="/api/options/info",
     *   @OA\Response(
     *       response="200",
     *       description="success",
     *       @OA\JsonContent(ref="#/components/schemas/info_options_responder")
     *   ),
     * )
     */
```

```
/**
 * @OA\Schema(
 *   schema="info_options_responder",
 *   type="object",
 *   required={"number_of_people_options", "headquarter_location_options"}
 * )
 */
class InfoOptionsResponder extends BaseResponder
{
    /**
     * @OA\Property(
     *   property="number_of_people_options",
     *   type="object",
     *   example={1: "~5人", 2: "5~10人"}
     * ),
     */
    private $numberOfPeopleOptions;

    /**
     * @OA\Property(
     *   property="headquarter_location_options",
     *   type="object",
     *   example={1: "北海道", 2: "青森県"}
     * ),
     */
    private $headquarterLocationOptions;
```

schema においては object type を使用します。property の object の key value が固定であればさらに定義できますが、このケースのように固定じゃない場合には array が使えるかもしれません（この形は本運用でまだ使えていないので今後の宿題にして、かけたら更新します）。


# 終わりに

書き慣れるまでなかなか辛いです。慣れてしまうとパターンも少ないので案外サクサクかけます。

このannotationを使ったdocumentから実際のAPIレスポンスをテストできるのですが、それについては他の記事で書こうと思います。