Help us understand the problem. What is going on with this article?

【CraftCMS】ElementAPIでフロントエンドにjsonだけ返す

スコープの切り分け問題

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、だいぶお気に入りです。
スクリーンショット 2019-07-23 21.51.26.png

プラグインの実モジュール部分は割愛しますが、element-api.phpだけをイジればよいので
非常に楽。とにかく楽。

実装方法

プラグインの入れ方は単純にcomposerなりで導入するので端折ります。

element-api.php
<?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が受け取れるというスンポーです。

おわり。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした