CakePHP3フレームワークを使用し、REST APIを作成する

#この記事について
この記事では、CakePHPを使ったREST APIの作成方法を紹介します。

#バックグラウンド、モチベーション
前提に、自分はCakePHPを会社研修レベルでしか学んでいません。しかし、MVCというフレームワークについては、Java Spring、Ruby、Python Djangoの実務経験が2年程あるため、仕組みは理解していました。

モチベーションは、以下２点です。
- REST APIとは何か、作りながら理解したい
- 複数言語で１つのアプリを作成してみたい

#REST APIとは
自分の解釈でAPIを説明すると、以下になります。
「一般のWEBアプリでは、HTTP Request(POST&GET)を投げるとHTMLファイルが返ってくるが、REST　APIでは、HTTP Request(POST&GET)を投げて返ってくるのはデータ、主にjson形式。」

つまり、このREST APIを作成すると、異なる言語を一つのアプリに内在させることができます。何を言っているのかを具体例で説明します。

例えば、以下の例を考えてください。
Python　DjangoベースのWEBアプリがあるとして、最新のニュースをデータベースから取り出し、ページに出したいという要件があるとします。
また、「https\://xxx.com/todaysnews.json」というHTTPリクエストを投げると、本日のニュースの情報をデータベースから取り出し、json形式で返すCakePHPベースのREST　APIがあるとします。
この場合、Djangoのコード上で「https\://xxx.com/todaysnews.json」というリクエストをCakePHP側に投げ、返ってきたjson形式のデータをDjango上で整えて、HTMLに設置する、ということができます。
※実際にはDjangoもCakePHPもバックエンド側の言語なので、これらをつなぐメリットはあまりないと思いますが、あくまで一例です。

#手順
以下を参考にしました。
https://www.discussdesk.com/restful-api-in-cakephp3-with-mysql.htm

#下準備
以下を用意しておく必要があります。
1. MySQLに接続された状態のCakePHP
2. レコードが登録されたMySQLデータベース

1については、CakePHPの作成方法は以下を参考にしてください。
https://book.cakephp.org/3.0/en/tutorials-and-examples/cms/installation.html

作成後、app.php内のデータベース接続情報を更新し、データベースに接続してください。
また、必ずHTTPサーバーを立ち上げ、ブラウザからCakePHPのホーム画面が見えるようにしておいてください。

以下のようなページが見えるはずです。
![Screenshot 2019-07-22 at 5.06.10 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/65bce238-186c-795b-2741-88948aeec54b.png)

2について、
**「手順」**にあるリンクでは、データベースの準備について説明がないのですが、TopicsというテーブルがローカルのMySQLにある前提で話しているため、そのまま実装するとエラーになります。そこで、データベースを作成したあと、以下のクエリを実装して下さい。

```sql

CREATE TABLE topics (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
name VARCHAR(255),
description TEXT
);

INSERT INTO test.topics VALUES (1, 1,'topic1','description') 
```

#実装
####1. REST API用にルート設定を行う
具体的には、config/routes.phpに、以下の２行を追加します。

```php3
Router::scope('/', function (RouteBuilder $routes) {
    // Register scoped middleware for in scopes.
    $routes->registerMiddleware('csrf', new CsrfProtectionMiddleware([
        'httpOnly' => true
    ]));
    #以下２行を追加
    $routes->resources('Topics');
    $routes->setExtensions(['json','xml']);
```
これにより、「http\://yourdomain/Topics/index.json」のようなリクエストがあると、CakePHPは、TopicsControllerのindexメゾットを呼び出し、結果をjson形式で返すことができます。

####2.TopicsControllerを用意する
src/Controller配下に、TopicsController.phpを作成し、以下のコードを記述します。

```php3
<?php

namespace App\Controller;

use App\Controller\AppController;
use Cake\Cache\Cache;
class TopicsController extends AppController
{
    public function initialize(){

    parent::initialize();
    $this->loadComponent('RequestHandler');

}
    public function index(){
    // find('all') get all records from Topics model
    // We uses set() to pass data to view
    $topics = $this->Topics->find('all');
    $this->set([
        'topics'=>$topics,
        '_serialize'=>['topics']
    ]);
}
```

これにより、Topicsテーブル内でfind('all')に該当する、つまり**「下準備」**で挿入されたレコードが、json形式で返される設定ができたと思います。実際に、HTTPリクエストを投げてみましょう。

![#REST_API_Sample_Demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/cd0c12e6-eb2b-17aa-3338-796e72cb2092.gif)

#最後に
この記事では、CakePHPを使ったREST APIの作成方法を紹介しました。自分はAPIというのが具体的にどういうものなのか、また複数言語でのアプリ実装を行ったことがなかったため、json形式でリスポンスが返ってくるのを目の当たりにした際、REST APIがなんなのかがはっきりわかったと感じました。
この記事にはありませんが、実際にこのjsonをPythonで受け取り、加工してみたりもしました。
わからないことがあれば、気軽にコメントください。