CakePHP3でjsonを返すAPIをCakePHPの流儀に従って記述量少なく書きたい人生だった


素人の投稿なので間違っていたら教えてください。

やりたいこと

wget http://xxx/api/apples.json
{
  "apples": [
    "Tsugaru",
    "Fuji"
  ]
}

…を出来る限り短いコード量で作りたい。
CakePHPの流儀に従ったら短くなるはずだ。

Note

いやいや、以下を返すべきだろ、などなどは本質的ではないので目をつぶってね。

["Tsugaru", "Fuji"]

routes.php

Router::extensions(['json']);
Router::prefix('api', function ($routes) {
    $routes->resources('Apples');
});

resourcesはREST APIのインタフェースを作ってくれる。
今回の場合は index のみ許可すべきですが、本質的ではないので省略。

controller

namespace App\Controller\Api; // napmespaceとdirectoryは Api の配下
use Cake\Controller\Controller;

class ApplesController extends Controller
{
    public function initialize()
    {
        parent::initialize();
        $this->loadComponent('RequestHandler');
    }

    public function index($mode = null) {
        $this->viewBuilder()->setClassName('Json'); // .jsonなしでもOKにする
        $apples = ["Tsugaru", "Fuji"];
        $this->set([
            'apples' => $apples,
            '_serialize' => ['apples']
        ]);
    }
}

JsonView を使う方法も (Thx to @juner)

JsonView を使うともっときれいにかけそうです。
https://book.cakephp.org/3/ja/views/json-and-xml-views.html#json

Point (Thx to @nojimage )

  • コントローラの置き場を Controller/Api/ApplesController にしたい
  • コントローラのnamespaceを namespace App\Controller\Api; にしたい

といった場合は、プレフィックスルーティング を使用します。

["Tsugaru", "Fuji"] だけを返したい。

        $this->set([
            'apples' => $apples,
            '_serialize' => 'apples'
        ]);

Thanks to @tomcat0090 !