CakePHPのrestfulインタフェースにAngularJSからリクエストしてデータを取得
CakePHPで効率的にrestful APIを開発
AngularJSでCRUD操作を行うアプリケーションを開発するにはどうすればよいか?
本エントリーでは、
- バックエンドにCakePHP
- フロントエンドにAngularJS
を利用した開発ノウハウをCRUD操作の「Read」に焦点をあてて書いてみたい。
バックエンド側については、CakePHPで効率的に開発を進めることができる。具体的には公式ドキュメントの以下のURLを参考にrestful apiを組むことができる。
http://book.cakephp.org/2.0/ja/development/rest.html
RecipesController.phpを作成し、以下のアクションを作成した。
class RecipesController extends AppController { public $components = array('RequestHandler'); public function index() { $recipes = $this->Recipe->find('all'); $this->set(array( 'recipes' => $recipes, '_serialize' => array('recipes') )); } }
簡略化のためにindexアクションのみ(Readのみ)を作成することにした。
Readするデータが必要になるので、recipesテーブルを以下のSQLのように定義する。
CREATE TABLE IF NOT EXISTS `recipes` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` text COLLATE utf8_unicode_ci, `body` text COLLATE utf8_unicode_ci, `created` datetime DEFAULT NULL, `modified` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=3 ; INSERT INTO `recipes` (`id`, `title`, `body`, `created`, `modified`) VALUES (1, 'test recipe', 'recipe content', '2014-02-19 11:43:20', '2014-02-19 11:43:20'), (2, 'test recipe2', 'recipe content2', '2014-02-19 11:43:40', '2014-02-19 11:43:40');
最後にroutes.phpに以下を追記する。
Router::mapResources("recipes"); Router::parseExtensions();
バックエンド側の準備が完了したのでブラウザで、
/recipes.json
にアクセスしてみる。
{ "recipes": [ { "Recipe": { "id": "1", "title": "test recipe", "body": "recipe content", "created": "2014-02-19 11:43:20", "modified": "2014-02-19 11:43:20" } }, { "Recipe": { "id": "2", "title": "test recipe2", "body": "recipe content2", "created": "2014-02-19 11:43:40", "modified": "2014-02-19 11:43:40" } } ] }
json形式でデータを取得することができた。
なお、本エントリーに書くにあたり以下のURLでアクセスできるようにWindowsローカルサーバを構成して確認した。
restful-cakephp.local/recipes.json
AngularJSからrestful APIを利用する
CakePHPを用いたバックグラウンド側のAPIの準備が整ったのでAngularJS側からリクエストを送信する。APIの呼び出し部分のJSは以下のようにした。
function Get_request($scope, $http) { $http.get('http://restful-cakephp.local/recipes.json'). success(function(data) { $scope.recipes = data.recipes; }); }
Get_requestという関数を一つ作成し、その中でCakePHPのRestful APIをリクエストし結果を$scopeに格納し、テンプレート側で利用可能な状態にしている。
次にテンプレート側
<!doctype html> <html ng-app> <head> <title>AngularJS requests CakePHP restful API</title> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.min.js"></script> <script src="get_request.js"></script> </head> <body> <div ng-controller="Get_request"> <ul> <li ng-repeat="recipe in recipes">[{{recipe.Recipe.id}}]{{recipe.Recipe.title}}</li> </ul> </div> </body> </html>
liにng-repeatを定義して繰り返し処理を行っている。
- ng-app
- ng-controller
- ng-repeat
AngularJSで利用頻度の高い3つのディレクティブを利用してテンプレート側を組んでみた。Get_request関数でバックエンド側のAPIを呼び出しているが、以下のように書くことも可能。
controllers.jsにコントローラをまとめる
AngularJSを構造化するために、アプリケーションの本体app.jsとコントローラcontroller.jsに分離します。app.jsを以下のように定義します。
(function() { var ajs = angular.module('myApp', ['myApp.controllers']); }());
そして、controller.jsは以下のようにしました。
(function() { var ajs = angular.module('myApp.controllers', []); ajs.controller('AppCtrl', function($scope, $rootScope, $http) { $rootScope.appUrl = "http://restful-cakephp.local"; }); ajs.controller('GetRequestCtrl', function($scope, $rootScope, $http) { var load = function() { console.log('load中です'); $http.get($rootScope.appUrl + '/recipes.json') .success(function(data, status, headers, config) { $scope.recipes = data.recipes; }); } load(); }); }());
テンプレート側のng-controllerの定義の仕方によりますが、AppCtrlでアプリケーション全体で処理する部分を書き、GetRequestCtrlのような個別の処理を以後並列に書いていくイメージです。
テンプレート側は以下のように変更しました。
<!doctype html> <html ng-app="myApp"> <head> <title>AngularJS requests CakePHP restful API</title> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.min.js"></script> <script src="app.js"></script> <script src="controllers.js"></script> </head> <body ng-controller="AppCtrl"> <div ng-controller="GetRequestCtrl"> <ul> <li ng-repeat="recipe in recipes">[{{recipe.Recipe.id}}]{{recipe.Recipe.title}}</li> </ul> </div> </body> </html>
コードの構造化に伴い、
- ng-app=”myApp”
- ng-controller=”AppCtrl”
のようにアプリケーション名とbodyタグにAppCtrlを指定している点が異なっています。コードを構造化すると開発方法のイメージがより具体的に考えらえるようになります。
Restfulとは?
今回のエントリーでは、データを取得するだけにしましたが、実際のCRUD処理では、
- データの取得
- 追加
- 変更
- 削除
の処理が必要になります。
上に載せたコードでは、コントローラ側からAngularJSのgetリクエストを送信していますが、データを追加する際にはPostリクエスト、変更する場合はPutリクエストを利用して、バックエンド側にリクエストを送信すれば、CakePHP側で適切にリクエストの処理を判別しデータが処理されます。
参考