CakePHP3でREST APIをちゃちゃっと作る方法

# CakePHP3でREST APIをちゃちゃっと作る方法

CakePHP3でREST APIをお手軽に作成してみました。
[CRUD Plugin](https://github.com/FriendsOfCake/crud)を利用して作成する方法になります。

2系とあまり変わらないかもしれませんがCakePHPでREST APIを作る方法として読んでいただけると嬉しいです。

参考記事
[How to build a CakePHP 3 REST API in minutes](http://www.bravo-kernel.com/2015/04/how-to-build-a-cakephp-3-rest-api-in-minutes/)

## CRUD Pluginの特徴
* 設置が簡単
* 設置するだけで、CRUDの処理が使用可能
* 独自処理を作成する場合はCRUD Plugin の Events機能を使用する。

## REST API 作成手順
1. CRUD Pluginの追加
2. APIの有効化

### CRUD Pluginの追加

まずはcomposerでPlugiinを追加してください。

```
    // CakePHP3
    composer require friendsofcake/crud:~4.0

    // CakePHP2 
    composer require friendsofcake/crud:~3.0
```

### APIの有効化
* API対象のControllerの指定

config/routes.php に下記を記述

```php
    // PostsControllerをAPI化
    Router::scope('/', function ($routes) {
        $routes->resources('Posts');
    }
```
* APIの設定

AppController に下記を記述

```php
class AppController extends Controller
{

    use \Crud\Controller\ControllerTrait;

    /**
    * components
    *
    *
    */
    public $components = [
        'RequestHandler',
        'Crud.Crud' => [
            // API化対象アクション
            'actions' => [
                'Crud.Index',
                'Crud.View',
                'Crud.Add',
                'Crud.Edit',
                'Crud.Delete'
            ],
            // リスナー指定
            'listeners' => [
                'Crud.Api',
                'Crud.ApiPagination',
                'Crud.ApiQueryLog'
            ]
        ]
    ];    
```

* APIのレスポンス形式の設定

config/routes.php に下記を記述

```php
    // json、xml形式の許可
    Router::extensions(['json', 'xml']);
```

ここまでの設定で下記のアクションが使用可能になります。

```
    index: [GET] http://localhost/test_app/posts.json
    view:  [GET] http://192.168.56.10/rest_api/posts/1.json
    add:   [POST] http://localhost/test_app/posts.json
    edit:  [PUT] http://localhost/test_app/posts/1.json
    delete:[DELETE] http://localhost/test_app/posts/1.json
```


レスポンス例

```json
    {
        success: true,
        data: [
            {
                id: 1,
                name: "test",
                created: null,
                modifited: null
            }
        ],
        pagination: {
            page_count: 1,
            current_page: 1,
            has_next_page: false,
            has_prev_page: false,
            count: 1,
            limit: null
        },
        queryLog: {
             default: [
                {
                    query:
                        "
                         SELECT
                             Posts.id AS "Posts__id",
                             Posts.name AS "Posts__name", 
                             Posts.created AS "Posts__created",
                             Posts.modifited AS "Posts__modifited"
                         FROM posts Posts
                         LIMIT 20
                         OFFSET 0
                        "
                    ,
                    took: 0,
                    params: [ ],
                    numRows: 1,
                    error: null
                },
                {
                    query: "SELECT (COUNT(*)) AS "count" FROM posts Posts",
                    took: 0,
                    params: [ ],
                    numRows: 1,
                    error: null
                }
        ],
}
```


## 独自処理
1. CRUD PluginのEvents機能

CRUD Pluginには下記のEvents機能が準備されています。
(コールバックメソッドとほぼ同意)

* beforeFilter
* startup
* beforeHandle
* beforePaginate
* afterPaginate
* recordNotFound
* invalidId
* setFlash
* beforeRender
* beforeRedirect
* beforeSave
* afterSave
* beforeFind
* afterFind
* beforeDelete
* afterDelete


```php
    // 実装方法例
    public function index() {
        $this->Crud->on('beforePaginate', function(Event $event) {

            // Search Pluginの検索条件の追加
            $event->subject->query = $this->Posts->find(
                'search',
                $this->request->query
            );

        });
        return $this->Crud->execute();
    }
```