cakePHP2インストール
cakephp-2.8.4をgitでworkspaceにDLする。
$ cd workspace $ git clone -b 2.x git://github.com/cakephp/cakephp.git $ chmod 0777 -R ./cakephp/app/tmp/
今回apacheの公開ディレクトリが workspace/htdocs/なので以下の設定が必要。
$ mv ./cakephp/app/webroot ./htdocs
/cakephp/app/webroot/index.php
... if (!defined('ROOT')) { //define('ROOT', dirname(dirname(dirname(__FILE__)))); // ↓以下に変更↓ define('ROOT', dirname(dirname(__FILE__)) . DS . 'cakephp'); } ... if (!defined('APP_DIR')) { //define('APP_DIR', basename(dirname(dirname(__FILE__)))); // ↓以下に変更↓ define('APP_DIR', 'app'); } ...
SQLite3の設定
ここでは記事マスタ(mas_entries)とカテゴリ(met_categories)という2つのテーブルを想定する。
それぞれ主キー(entry_id, category_id)と登録日時(created), 更新日時(modified), 論理削除日時(deleted)をもつ。
$ cd workspace $ mkdir sqlite3 $ vi sqlite3/create-table.sql
create-table.sql
CREATE TABLE `mas_entries` ( `entry_id` INTEGER PRIMARY KEY AUTOINCREMENT, `created` datetime NULL, `modified` datetime NULL, `deleted` datetime NULL, `title` VARCHAR(50), `content` VARCHAR(1000), `category_id` INTEGER ); CREATE TABLE `met_categories` ( `category_id` INTEGER PRIMARY KEY AUTOINCREMENT, `created` datetime NULL, `modified` datetime NULL, `deleted` datetime NULL, `name` VARCHAR(50), `display_order` INTEGER ); BEGIN TRANSACTION; INSERT INTO `met_categories` (`created`, `modified`, `name`, `display_order`) VALUES(datetime('now', 'localtime'), datetime('now', 'localtime'), 'ニュース', 1); INSERT INTO `met_categories` (`created`, `modified`, `name`, `display_order`) VALUES(datetime('now', 'localtime'), datetime('now', 'localtime'), '商品情報', 2); INSERT INTO `met_categories` (`created`, `modified`, `name`, `display_order`) VALUES(datetime('now', 'localtime'), datetime('now', 'localtime'), 'IR情報', 3); COMMIT;
$ sqlite3 sqlite3/rest-test.sqlite3 < sqlite3/create-tables.sql $ chmod 0777 sqlite3 $ chmod 0666 sqlite3/rest-test.sqlite3 $ mv cakephp/app/Config/database.php.default cakephp/app/Config/database.php $ vi cakephp/app/Config/database.php
cakephp/app/Config/database.php DBの設定を以下のように変更。
... public $default = array( 'datasource' => 'Database/Sqlite', 'persistent' => false, 'database' => '/home/test/workspace/sqlite3/rest-test.sqlite3', 'prefix' => '', 'encoding' => 'utf8', ); ...
RESTの設定
cakephp/app/Config/routes.php の require CAKE . 'Config' . DS . 'routes.php'; より前にRESTの設定を記述する。
/** * REST config */ Router::mapResources('entries'); Router::mapResources('categories'); Router::parseExtensions();
cakephp/app/Model にモデルファイル追加。
cakephp/app/Model/Entry.php
<?php class Entry extends AppModel { /** * モデル名 */ public $name = 'Entry'; /** * 使用テーブル */ public $useTable = 'mas_entries'; /** * 主キー */ public $primaryKey = 'entry_id'; /** * list取得時表示フィールド */ public $displayField = 'title'; /** * リレーション */ public $belongsTo = [ 'Category' => [ 'className' => 'Category', 'foreignKey' => 'category_id', ], ]; }
cakephp/app/Model/Category.php
<?php class Category extends AppModel { /** * モデル名 */ public $name = 'Category'; /** * 使用テーブル */ public $useTable = 'met_categories'; /** * 主キー */ public $primaryKey = 'category_id'; /** * list取得時表示フィールド */ public $displayField = 'name'; }
cakephp/app/Controller にコントローラファイル追加。
cakephp/app/Controller/RestController.php
<?php class RestController extends AppController { /** * コンポーネント */ public $components = ['RequestHandler']; /** * メインモデル */ public $mainModel; /** * 一覧表示 */ public function index() { $mainModel = $this->mainModel; $all = $this->$mainModel->find('all'); $this->set([ 'all' => $all, '_serialize' => ['all'] ]); } /** * 詳細表示 */ public function view($id) { $mainModel = $this->mainModel; $conditions = [ [$this->$mainModel->name . '.' . $this->$mainModel->primaryKey => $id] ]; $first = $this->$mainModel->find('first', compact('conditions')); $this->set([ 'first' => $first, '_serialize' => ['first'] ]); } /** * 登録 */ public function add() { $mainModel = $this->mainModel; $this->$mainModel->create(); if ($this->$mainModel->save($this->request->data)) { $message = 'Saved'; } else { $message = 'Error'; } $this->set([ 'message' => $message, '_serialize' => ['message'] ]); } /** * 更新 */ public function edit($id) { $mainModel = $this->mainModel; $this->$mainModel->id = $id; if ($this->$mainModel->save($this->request->data)) { $message = 'Saved'; } else { $message = 'Error'; } $this->set([ 'message' => $message, '_serialize' => ['message'] ]); } /** * 論理削除 */ public function delete($id) { $mainModel = $this->mainModel; $conditions = [ [$this->$mainModel->name . '.' . $this->$mainModel->primaryKey => $id] ]; $message = 'Error'; if ($first = $this->$mainModel->find('first', compact('conditions'))) { $first[$this->$mainModel->name]['deleted'] = date("Y-m-d H:i:s"); if ($this->$mainModel->save($first)) { $message = 'Deleted'; } } $this->set([ 'message' => $message, '_serialize' => ['message'] ]); } }
cakephp/app/Controller/EntriesController.php
<?php App::uses('RestController', 'Controller'); class EntriesController extends RestController { /** * 使用モデル */ public $uses = ['Entry']; /** * メインモデル */ public $mainModel = 'Entry'; }
cakephp/app/Controller/CategoriesController.php
<?php App::uses('RestController', 'Controller'); class CategoriesController extends RestController { /** * 使用モデル */ public $uses = ['Category']; /** * メインモデル */ public $mainModel = 'Category'; }
Backboneのインストール
workspace/htdocs/js/lib/ を作成し,
・backbone-min.js
・jquery.min.js
・require.js
・text.js
・underscore-min.js
を設置。それぞれのファイルはWEB上から取得。
workspace/htdocs/app を作成し,以下のディレクトリ構造を作成する。
app/
├ Collection/
├ Config/
├ Model/
├ Template/
└ View/
次に設定ファイルを作成。
workspace/htdocs/app/Config/require_config.js
var require = { baseUrl: '/app/', paths: { 'jquery': '/js/lib/jquery.min', 'underscore': '/js/lib/underscore-min', 'backbone': '/js/lib/backbone-min', 'text': '/js/lib/text', }, shim: { 'backbone': { deps: ['jquery', 'underscore'], exports: 'Backbone' }, 'text': { deps: ['backbone'], exports: 'Text' } } };
メインスクリプトを設置。
workspace/htdocs/app/main.js
define(function(require){ // ライブラリ var $ = require('jquery'); var _ = require('underscore'); var Backbone = require('backbone'); });
htmlファイルを設置。
workspace/htdocs/entries.html
最低限のインストールは終了。
BackboneのModel,Collectionの作成
workspace/htdocs/app/Model/AppModel.js
define(function(require){ var Backbone = require('backbone'); return Backbone.Model.extend({ /** * URL */ url: function() { if (this.id) { return this.urlRoot + '/' + this.id + '.json'; } else { return this.urlRoot + '.json'; } }, /** * parse */ parse: function(response) { var data = response; if (typeof(data.first) !== 'undefined') { for (var i in data.first) { data[i] = data.first[i]; } delete(data.first); } if (typeof(data[this.name]) !== 'undefined') { for (var i in data[this.name]) { data[i] = data[this.name][i]; } delete(data[this.name]); } return data; } }); });
workspace/htdocs/app/Model/Entry.js
define(function(require){ var Backbone = require('backbone'); var AppModel = require('Model/AppModel'); return AppModel.extend({ /** * モデル名 */ name: 'Entry', /** * URL ROOT */ urlRoot : '/entries', /** * idAttribute */ idAttribute: 'entry_id' }); });
workspace/htdocs/app/Model/Category.js
define(function(require){ var Backbone = require('backbone'); var AppModel = require('Model/AppModel'); return AppModel.extend({ /** * モデル名 */ name: 'Category', /** * URL ROOT */ urlRoot : '/categories', /** * idAttribute */ idAttribute: 'category_id' }); });
workspace/htdocs/app/Collection/AppCollection.js
define(function(require){ var Backbone = require('backbone'); return Backbone.Collection.extend({ /** * parse */ parse: function(response) { if (typeof(response.all) !== 'undefined') { return response.all; } else { return response; } } }); });
workspace/htdocs/app/Collection/Entries.js
define(function(require){ var Backbone = require('backbone'); var AppCollection = require('Collection/AppCollection'); var Entry = require('Model/Entry'); return AppCollection.extend({ /** * コレクション名 */ name: 'Entries', /** * モデル */ model: Entry, /** * URL */ url: '/entries.json' }); });
workspace/htdocs/app/Collection/Categories.js
define(function(require){ var Backbone = require('backbone'); var AppCollection = require('Collection/AppCollection'); var Category = require('Model/Category'); return AppCollection.extend({ /** * コレクション名 */ name: 'Categories', /** * モデル */ model: Category, /** * URL */ url: '/categories.json' }); });
準備完了。
BackboneでRESTテスト
先ほど作ったworkspace/htdocs/app/main.jsを修正しながらテスト
1. 一覧取得テスト
var Categories = require('Collection/Categories'); var categories = new Categories(); categories.fetch({ success: function(categories) { console.log(categories); } });
2. 登録テスト
var Entry = require('Model/Entry'); var entry = new Entry(); entry.set({ title: 'ニューステスト', content: 'これは初めての投稿です。', category_id: 1 }); entry.save();
3. 1件取得テスト
var Entry = require('Model/Entry'); var entry = new Entry(); entry.id = 1; entry.fetch({ success: function() { console.log(entry); } });
4. 更新テスト
var Entry = require('Model/Entry'); var entry = new Entry(); entry.set({ entry_id: 1, title: 'これは書き換えテスト' }); entry.save();
5. 削除テスト
var Entry = require('Model/Entry'); var entry = new Entry(); entry.id = 1; entry.fetch({success: function(){ entry.destroy(); }});