スコープの切り分け問題
CraftCMSではCPで定義したsectionやfieldのhandleをtwigでモリモリ書いて出力する、
いわばオーソドックスなMVCデザインパターンに則った構成です。
他のCMSをディスるわけではないですが某何とかPressとかは
テンプレートに<?php 〜 ?>みたいな記述がそこかしこで必要なもんで
個人的に可読性の低下を感じてしまい、あんまり好きじゃない得意じゃないです。
(´-`)oO( Timberとか使えばWord何とかもTwig使えるんだったかな… )
一方デフォルトでテンプレートエンジンを積んだCMSは(ある程度ですが)元のソースを大きく崩すことなく動的なアウトプットが可能であり、
それこそCraftやDrupalなんかはそこそこ見やすい&書きやすいのが取り柄の1つじゃないでしょうか。
そういう経験からこう考えていたもんです。
「CMSとかFrameworkのView部分はSmartyとかTwigとか使うのがセオリー。
テンプレートはフロントの人が作るから、データのアウトプットはバックエンドに任せて
じゃとりあえずテンプレートはダミーテキスト入れといて、あとで埋め込んどくから――」
ところが最近というかもう結構前からですが、
フロントエンドだけでViewを完結するような思想がウチの会社では主となってしまいました。
しまいましたって別に悪いこっちゃなくて、むしろデータこねこねはバックエンド、ドバドバはフロントエンドという切り分けが明確になったため、
余計なことを考えずに最後にecho $json;すれば完結するようになったのがとても楽。
ElementAPIとは
ということで本題ですが、まさに前述の実装を実現してくれる公式のプラグインがElementAPIです。
リポジトリはこちら
Endpointを定義して返却するjsonを設計,実装する & フロントエンドで叩いてもらう
これだけでデータを簡単に展開出来るAPI、だいぶお気に入りです。
プラグインの実モジュール部分は割愛しますが、element-api.phpだけをイジればよいので
非常に楽。とにかく楽。
実装方法
プラグインの入れ方は単純にcomposerなりで導入するので端折ります。
<?php
use Craft;
use craft\elements\Entry;
use craft\elements\Asset;
use craft\elements\Category;
use craft\helpers\UrlHelper;
use League\Fractal\TransformerAbstract;
return [
"endpoints" => [
"api/news/archives.json" =>
[
"elementType" => Entry::class,
'criteria' => [
'section' => 'News',
'orderBy' => 'postDate DESC',
],
'paginate' => $_GET['size'],
'elementsPerPage' => 9,
'pageParam' => 'size',
'transformer' => function (Entry $entry){
return [
'id' => $entry->id ,
'title' => $entry->n_title,
'main_img' => $entry->n_image->one()->url,
'time' => $entry->postDate->format("Y.M.d"),
'article' => preg_replace('/<p.*?>|<\/p>/mis', '', $entry->n_detail),
];
}
],
"api/news/<news_id:\d+>.json" => function($news_id){
return [
"elementType" => Entry::class,
'criteria' => [
'news_id' => $news_id,
'section' => 'News'
],
~ 省略 ~
];
}
];
ものすごいreturnします。
リストを取得したい場合は上のエンドポイント、詳細を取得したい場合はIDを付与して下のエンドポイントを実行すると
それぞれに対応した結果が取得出来ます。
ちょっと実ソースがものすごい長いのですいませんが省略します…。
上の大事な項目(全部大事だけど)は以下。
キー | 役割 |
---|---|
endpoints | アクセスするURLを定義 |
elementType | 取得したいデータの型を定義 |
criteria | 取得したいデータの基準(条件)を定義 |
transformer | データを加工したい場合はこのスコープで |
結果としてtransformer内でreturnしている内容がjsonとして出力されます。
フロントエンド側の人にはjs側で
https://morimorigohan.jp/api/news/archives.json
https://morimorigohan.jp/api/news/12.json
のようにアクセスしてもらえば
上記で予め設計した形のjsonが受け取れるというスンポーです。
おわり。