【CraftCMS】ElementAPIをセクションごとに分割する

公式（P&Tだから公式よな？）がリリースしている、
CraftCMSをRestfulAPIとして使えるプラグイン「[Element API](https://plugins.craftcms.com/element-api)」

ややこしい設定が不要ですぐ使えるのでイチ推しです。

# 基本のキ

インストール後configディレクトリにelement-api.phpが出来てるので
それをイジっていきます。

マニュアル通りに組む分には公式見れば大体どうにかなります。

```php:element-api.php
use craft\elements\Entry;
use craft\helpers\UrlHelper;

return [
    'endpoints' => [
        'news.json' => function() {
            return [
                'elementType' => Entry::class,
                'criteria' => ['section' => 'news'],
                'transformer' => function(Entry $entry) {
                    return [
                        'title' => $entry->title,
                        'url' => $entry->url,
                        'jsonUrl' => UrlHelper::url("news/{$entry->id}.json"),
                        'summary' => $entry->summary,
                    ];
                },
            ];
        },
        'news/<entryId:\d+>.json' => function($entryId) {
            return [
                'elementType' => Entry::class,
                'criteria' => ['id' => $entryId],
                'one' => true,
                'transformer' => function(Entry $entry) {
                    return [
                        'title' => $entry->title,
                        'url' => $entry->url,
                        'summary' => $entry->summary,
                        'body' => $entry->body,
                    ];
                },
            ];
        },
    ]
];
```

基本的にsectionごとに一覧、詳細を取ってくる形になると思いますが
これが増えていくとなかなか煩雑になります。

# 本題

2パターンあるっぽいですが、直感的なやつを。

### 手順1.section別のファイルを作る

例としてarticleセクションを切り出します。
一覧と詳細データ生成の処理を実装。

```php:api-articles.php
use craft\elements\Entry;

class Articles {
    public static function index(){
        return [
            'elementType' => Entry::class,
            'criteria' => [
                'section' => 'articles',
                'orderBy' => 'postDate DESC',
            ],
            //〜略〜//
        ];
    }

    public static function detail($id){
        return [
            'elementType' => Entry::class,
            'criteria' => ['section' => 'articles'],
            //〜略〜//
        ];
    }
}
```
### 手順2.コアファイルに追加する

もしかしてこれで終わり...？終わりなんです。

```php:element-api.php

include __DIR__ . '/api-articles.php';

return [
	"endpoints" => [
        /* 
            エンドポイントがたくさん入ってるスコープ
            ...
        */
		"api/articles/index" => function(){
			return Articles::index();
		},
		"api/articles/<id:\d+>" => function(){
			return Articles::detail($id);
		},
    ]
];
```

**めっちゃ楽**
**もっと流行れCraftCMS**

## もう1つのやり方（上級者向け）

規模にもよりますがconfig配下に裸でファイルを置くのが段々みっともなくなる量になった場合。
エンドポイントはエンドポイントで整理した方が美しいですね。

```sh
mkdir -p /config/endpoints
```

composerのautoloadに事前に含ませてしまう方法です。
composer.jsonにpsr-4規約としてロード対象のディレクトリとして登録します。

```json:composer.json
"autoload": {
    "psr-4": {
        "config\\endpoints\\": "config/endpoints"
    }
}
```

あとはautoloaderをリロードします。
（全クラスがクラスマップに含まれるようにoオプションを付けるらしい）
これによってrequireやincludeが不要になるのでお好きに実装しましょう。

```sh
composer dump-autoload -o
```

こっちの方がいいのでは...？と思いましたが
自分がpsr-4の思想だったりFramework慣れしていないため前者を採用しました。
要は力不足です。

あとは元ファイル同様の組み方でOK

```php
use craft\elements\Entry;

return [
	"endpoints" => [
  		"api/articles/index" => function(){
            return [
                'elementType' => Entry::class,
                'criteria' => [
                    'section' => 'articles',
                    'orderBy' => 'postDate DESC',
                ],
                //〜略〜//
            ];
		},
		"api/articles/<id:\d+>" => function(){
			return [
                'elementType' => Entry::class,
                'criteria' => ['section' => 'articles'],
                //〜略〜//
            ];
		},
    ]
];
```

**おわり。**