This document is for CakePHP's development version, which can be significantly different from previous releases.
You may want to read current stable release documentation instead.

REST

最近のアプリケーションプログラマーは、サービスのコア機能を ユーザーにオープンにする必要があると気付き始めています。 簡単に提供でき、自由にコア API にアクセスできれば、広く受け入れられ、 マッシュアップされたり、簡単に他のシステムと統合できます。

簡単にあなたの作ったアプリケーションロジックにアクセスさせる方法は色々ありますが、 REST はその中でもすばらしい方法でしょう。とてもシンプルで、大抵は XML ベース (SOAP のようなものではなく、単純な XML のこと) で、HTTP ヘッダーによって制御されます。 CakePHP を使って REST の API を提供するのはすごく簡単です。

簡単なセットアップ

REST を動かすための手っ取り早い方法は、 config/routes.php ファイルに リソースルート をセットアップするための数行を追記することです。

一度、Router が REST リクエストを、コントローラーのアクションにマッピングしておけば、 そのコントローラーのアクションのロジックの作成に移ることができます。 基本的なコントローラーのサンプルは下記のようになります。

// src/Controller/RecipesController.php
class RecipesController extends AppController
{
    public function initialize(): void
    {
        parent::initialize();
        $this->loadComponent('RequestHandler');
    }

    public function index()
    {
        $recipes = $this->Recipes->find('all')->all();
        $this->set('recipes', $recipes);
        $this->viewBuilder()->setOption('serialize', ['recipes']);
    }

    public function view($id)
    {
        $recipe = $this->Recipes->get($id);
        $this->set('recipe', $recipe);
        $this->viewBuilder()->setOption('serialize', ['recipe']);
    }

    public function add()
    {
        $this->request->allowMethod(['post', 'put']);
        $recipe = $this->Recipes->newEntity($this->request->getData());
        if ($this->Recipes->save($recipe)) {
            $message = 'Saved';
        } else {
            $message = 'Error';
        }
        $this->set([
            'message' => $message,
            'recipe' => $recipe,
        ]);
        $this->viewBuilder()->setOption('serialize', ['recipe', 'message']);
    }

    public function edit($id)
    {
        $this->request->allowMethod(['patch', 'post', 'put']);
        $recipe = $this->Recipes->get($id);
        $recipe = $this->Recipes->patchEntity($recipe, $this->request->getData());
        if ($this->Recipes->save($recipe)) {
            $message = 'Saved';
        } else {
            $message = 'Error';
        }
        $this->set([
            'message' => $message,
            'recipe' => $recipe,
        ]);
        $this->viewBuilder()->setOption('serialize', ['recipe', 'message']);
    }

    public function delete($id)
    {
        $this->request->allowMethod(['delete']);
        $recipe = $this->Recipes->get($id);
        $message = 'Deleted';
        if (!$this->Recipes->delete($recipe)) {
            $message = 'Error';
        }
        $this->set('message', $message);
        $this->viewBuilder()->setOption('serialize', ['message']);
    }
}

しばしば、RESTful なコントローラーは、リクエストの種類ごとに異なるビューファイルを扱うために パースされた拡張子を使用します。REST リクエストが処理できるようになったので、XML ビューなどが 作成できます。CakePHP の組み込みの JSON と XML ビュー を利用して JSON ビューを作成できます。組み込みの XmlView を扱うために、 _serialize というビュー変数を定義します。この特別なビュー変数は、 XmlView の中に 取り込まれ、出力結果が XML に変換されます。

XML データに変換する前にデータを修正したい場合は、 _serialize ビュー変数ではなく、 ビューファイルを使いましょう。RecipesController に対する REST ビューを templates/Recipes/xml 以下に置きます。 Xml クラスを使えば、 このビューファイル内で簡単に素早く XML を出力させることができます。 下記に index ビューの例を載せます。

// templates/Recipes/xml/index.php
// $recipes 配列に対して いくつかのフォーマットと操作を行う。
$xml = Xml::fromArray(['response' => $recipes]);
echo $xml->asXML();

Cake\Routing\Router::extensions() を使って、特定のコンテンツタイプを扱う場合、 CakePHP は自動的にそのタイプに対応するビューヘルパーを探します。 ここではコンテンツタイプとして XML を利用していて、標準のビルトインヘルパーは存在しないのですが、 もし自作のヘルパーがあれば CakePHP はそれを自動読込みして利用可能にします。

レンダリングされた XML は下記のような感じになります。

<recipes>
    <recipe>
        <id>234</id>
        <created>2008-06-13</created>
        <modified>2008-06-14</modified>
        <author>
            <id>23423</id>
            <first_name>Billy</first_name>
            <last_name>Bob</last_name>
        </author>
        <comment>
            <id>245</id>
            <body>Yummy yummmy</body>
        </comment>
    </recipe>
    ...
</recipes>

edit アクションのロジックを作るのは少しだけトリッキーです。XML 出力 の API を提供する場合、 入力も XML で受付けるほうが自然です。心配せずとも、 Cake\Controller\Component\RequestHandlerCake\Routing\Router クラスが取り計らってくれます。 POST もしくは PUT リクエストのコンテンツタイプが XML であれば、入力データは CakePHP の Xml クラスに渡され、配列に変換され、 $this->request->getData() に入ります。 この機能によって、XML と POST データの処理はシームレスになるのです。コントローラーもモデルも XML の入力を気にせずに、 $this->request->getData() のみを扱えば良いのです。

他のフォーマットのインプットデータ

REST アプリケーションの場合、様々なフォーマットのデータを扱います。 CakePHP では、 RequestHandlerComponent クラスが助けてくれます。 デフォルトでは、POST や PUT で送られてくる JSON/XML の入力データはデコードされ、 配列に変換されてから $this->request->getData() に格納されます。独自のデコード処理も RequestHandler::addInputType() を利用すれば追加可能です。

RESTful ルーティング

CakePHP の Router は、 RESTful なリソースルートへの接続は容易です。詳しくは、 RESTful なルーティング セクションをご覧ください。