CakePHPは便利そうなのだけれども、model部分で提供されるメソッドの挙動がイマイチわからない。自分としてはコマンドライン上で、これらのメソッドをガリガリと動かして調べてみたいのだけれども、そんな仕組みはなさそうなのでmodel部分を単体で動かせるようにしてみた。
CakePHPは便利そうなのだけれども、model部分で提供されるメソッドの挙動がイマイチわからない。自分としてはコマンドライン上で、これらのメソッドをガリガリと動かして調べてみたいのだけれども、そんな仕組みはなさそうなのでmodel部分を単体で動かせるようにしてみた。
最初に、CakePHPのサイトから、1.2.0.6311-betaを取ってきて適当な場所に展開して、出来たディレクトリをリネームします。
$ tar xvfz cake_1.2.0.6311-beta.tar.gz
$ mv cake_1.2.0.6311-beta piece_of_cake
次に、データベースの作成を行ないます。今回は、CakePHP レファレンスガイド中のhasManyの定義と問い合わせ使われているテーブルを作成する事にします。
ちなみにDBは、PostgreSQLを使っています。
$ createdb cakephp
$ psql cakephp < cakephp.sql
cakephp.sqlの内容は下記のようになっています。
CREATE TABLE users (
id serial NOT NULL PRIMARY KEY,
first_name character varying(200) NOT NULL,
last_name character varying(200) NOT NULL,
username character varying(200) NOT NULL,
"password" character varying(100) NOT NULL,
created timestamp DEFAULT NULL,
modified timestamp DEFAULT NULL
);
INSERT INTO users VALUES (1,'ジョン','アンダーソン','psychic','c4k3roxx','now','now');
SELECT pg_catalog.setval('users_id_seq', 1, true);
CREATE TABLE profiles (
id serial NOT NULL PRIMARY KEY,
name character varying(200) NOT NULL,
header_color character varying(200) NOT NULL,
user_id integer DEFAULT 0 NOT NULL,
created timestamp DEFAULT NULL,
modified timestamp DEFAULT NULL
);
INSERT INTO profiles VALUES (1,'Cool Blue', 'アクアマリン', 1);
SELECT pg_catalog.setval('profiles_id_seq', 1, true);
CREATE TABLE comments (
id serial NOT NULL PRIMARY KEY,
user_id integer NOT NULL,
body text NOT NULL,
created timestamp DEFAULT NULL,
modified timestamp DEFAULT NULL
);
INSERT INTO comments VALUES (1, 1, 'コメント1');
INSERT INTO comments VALUES (2, 1, 'コメント2');
INSERT INTO comments VALUES (3, 1, 'コメント3');
INSERT INTO comments VALUES (4, 1, 'コメント4');
INSERT INTO comments VALUES (5, 1, 'コメント5');
SELECT pg_catalog.setval('profiles_id_seq', 5, true);
データーベースの作成が終わったらConsoleコマンドを使ってmodel等の設定を行ないます。
最初に bakeを使ってappディレクトリの作成を行ないます。
$ cd piece_of_cake
$ rm -r app
$ cake/console/cake bake -app ./app
Hello foo,
Welcome to CakePHP v1.2.0.6311 beta Console
---------------------------------------------------------------
App : piece_of_cake
Path: /Library/WebServer/Documents/Projects/piece_of_cake
---------------------------------------------------------------
Bake Project
Skel Directory: /Library/WebServer/Documents/Projects/piece_of_cake/cake/console/libs/templates/skel
Will be copied to: /Library/WebServer/Documents/Projects/piece_of_cake/app
---------------------------------------------------------------
Look okay? (y/n/q)
[y] > y
Do you want verbose output? (y/n)
[n] > n
---------------------------------------------------------------
Created: app in /Library/WebServer/Documents/Projects/piece_of_cake/app
---------------------------------------------------------------
Creating file /Library/WebServer/Documents/Projects/piece_of_cake/app/views/pages/home.ctp
Wrote /Library/WebServer/Documents/Projects/piece_of_cake/app/views/pages/home.ctp
Welcome page created
Random hash key created for 'Security.salt'
$
次にデーターベースの設定をします。
$ cake/console/cake bake -app ./app
Hello foo,
Welcome to CakePHP v1.2.0.6311 beta Console
---------------------------------------------------------------
App : app
Path: /Library/WebServer/Documents/Projects/piece_of_cake/app
---------------------------------------------------------------
Your database configuration was not found. Take a moment to create one.
Database Configuration:
Name:
[default] >
Driver: (db2/firebird/mssql/mysql/mysqli/odbc/oracle/postgres/sqlite/sybase)
[mysql] > postgres
Persistent Connection? (y/n)
[n] >
Database Host:
[localhost] >
Port?
[n] >
User:
[root] > foo
Password:
>
The password you supplied was empty. Use an empty password? (y/n)
[n] > y
Database Name:
[cake] > cakephp
Table Prefix?
[n] >
Table encoding?
[n] > EUC-JP
Table schema?
[n] > public
---------------------------------------------------------------
The following database configuration will be created:
---------------------------------------------------------------
Name: default
Driver: postgres
Persistent: false
Host: localhost
Port:
User: foo
Pass:
Database: cakephp
Table prefix:
Schema: public
Encoding: EUC-JP
---------------------------------------------------------------
Look okay? (y/n)
[y] > y
Do you wish to add another database configuration?
[n] > n
Creating file /Library/WebServer/Documents/Projects/piece_of_cake/app/config/database.php
Wrote /Library/WebServer/Documents/Projects/piece_of_cake/app/config/database.php
$
そして、modelの設定を行ないます
$ cake/console/cake bake -app ./app
Hello foo,
Welcome to CakePHP v1.2.0.6311 beta Console
---------------------------------------------------------------
App : app
Path: /Library/WebServer/Documents/Projects/piece_of_cake/app
---------------------------------------------------------------
Interactive Bake Shell
---------------------------------------------------------------
[D]atabase Configuration
[M]odel
[V]iew
[C]ontroller
[P]roject
[Q]uit
What would you like to Bake? (D/M/V/C/P/Q)
> m
---------------------------------------------------------------
Bake Model
Path: /Library/WebServer/Documents/Projects/piece_of_cake/app/models/
---------------------------------------------------------------
Possible Models based on your current database:
1. User
2. Profile
3. Comment
Enter a number from the list above, or type in the name of another model.
>
長いので省略...
できあがった、モデルのソースはこんな感じ
CakePHPではリクエストがあると、app/index.phpが呼ばれます。ここでは、必要なインクルードファイルの読込やリクエストに応じたディスパッチ処理が行なわれます。
model単体で動かす場合は、ディスパッチ処理等は不要ですし、不要なインクルードファイルもあるので、試行錯誤しながら初期設定ファイルをつくりました。
$ cd piece_of_cake
$ ls
PieceOfCake.php cake/ index.php
app/ docs/ vendors/
作った初期設定ファイルを、展開して出来たディレクトリの下にPieceOfCake.phpとして置きます。
<?
if (!defined('PHP5')) {
define ('PHP5', (phpversion() >= 5));
}
/**
* Get Cake's root directory
*/
define('APP_DIR', 'app');
define('DS', DIRECTORY_SEPARATOR);
define('ROOT', dirname(__FILE__));
define('WEBROOT_DIR', 'webroot');
define('WWW_ROOT', ROOT . DS . APP_DIR . DS . WEBROOT_DIR . DS);
define('DISABLE_DEFAULT_ERROR_HANDLING',true);
/**
* This only needs to be changed if the cake installed libs are located
* outside of the distributed directory structure.
*/
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
//define ('CAKE_CORE_INCLUDE_PATH', FULL PATH TO DIRECTORY WHERE CAKE CORE IS INSTALLED DO NOT ADD A TRAILING DIRECTORY SEPARATOR';
define('CAKE_CORE_INCLUDE_PATH', ROOT);
}
if (function_exists('ini_set')) {
ini_set('include_path', ini_get('include_path') . PATH_SEPARATOR . CAKE_CORE_INCLUDE_PATH . PATH_SEPARATOR . ROOT . DS . APP_DIR . DS);
define('APP_PATH', null);
define('CORE_PATH', null);
} else {
define('APP_PATH', ROOT . DS . APP_DIR . DS);
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
}
require CORE_PATH . 'cake' . DS . 'basics.php';
$TIME_START = getMicrotime();
require CORE_PATH . 'cake' . DS . 'config' . DS . 'paths.php';
require LIBS . 'object.php';
require LIBS . 'inflector.php';
require LIBS . 'configure.php';
$bootstrap = true;
$url = null;
// require LIBS . 'file.php';
require LIBS . 'cache.php';
Configure::getInstance();
//require LIBS . 'session.php';
//require LIBS . 'security.php';
require LIBS . 'string.php';
require LIBS . DS . 'model' . DS . 'model.php';
require 'app_model.php';
Configure::write('debug', 2);
?>
ちゃんと動作するか、先ほど作成したPieceOfCake.phpをインクルードし、Userデータを取り出すUser.phpを作って確かめてみます。
<?php
ini_set('include_path', ini_get('include_path') . ':/Library/WebServer/Documents/Projects/piece_of_cake' );
include_once('PieceOfCake.php');
include_once('models/user.php');
function main(){
$User = new User();
if( $data=$User->findAll() ){
echo "++++++++++++++++ findAll()の返り値 +++++++++++++++\n";
print_r($data);
}
}
main();
?>
結果は下記のようになりました。ちゃんと動きます!
$ php User.php
++++++++++++++++ findAll()の返り値 +++++++++++++++
Array
(
[0] => Array
(
[User] => Array
(
[id] => 1
[first_name] => ジョン
[last_name] => アンダーソン
[username] => psychic
[password] => c4k3roxx
[created] => 2008-04-09 18:11:14.772833
[modified] => 2008-04-09 18:11:14.772833
)
[Profile] => Array
(
[id] => 1
[name] => Cool Blue
[header_color] => アクアマリン
[user_id] => 1
[created] =>
[modified] =>
)
[Comment] => Array
(
[0] => Array
(
[id] => 1
[user_id] => 1
[body] => コメント1
[created] =>
[modified] =>
)
[1] => Array
(
[id] => 2
[user_id] => 1
[body] => コメント2
[created] =>
[modified] =>
)
[2] => Array
(
[id] => 3
[user_id] => 1
[body] => コメント3
[created] =>
[modified] =>
)
[3] => Array
(
[id] => 4
[user_id] => 1
[body] => コメント4
[created] =>
[modified] =>
)
[4] => Array
(
[id] => 5
[user_id] => 1
[body] => コメント5
[created] =>
[modified] =>
)
)
)
)
次にProfileデータを取り出すProfile.phpを作って確かめてみます。
<?php
ini_set('include_path', ini_get('include_path') . ':/Library/WebServer/Documents/Projects/piece_of_cake' );
include_once('PieceOfCake.php');
include_once('models/profile.php');
function main(){
$Profile = new Profile();
if( $data=$Profile->findAll() ){
echo "++++++++++++++++ findAll()の返り値 +++++++++++++++\n";
print_r($data);
}
}
main();
?>
こちらも、問題なく動作しているようです。
$ php Profile.php
++++++++++++++++ findAll()の返り値 +++++++++++++++
Array
(
[0] => Array
(
[Profile] => Array
(
[id] => 1
[name] => Cool Blue
[header_color] => アクアマリン
[user_id] => 1
[created] =>
[modified] =>
)
[User] => Array
(
[id] => 1
[first_name] => ジョン
[last_name] => アンダーソン
[username] => psychic
[password] => c4k3roxx
[created] => 2008-04-09 18:11:14.772833
[modified] => 2008-04-09 18:11:14.772833
)
)
)
初期設定ファイルへのパスが通っていれば、どこのディレクトリからでも実行する事ができます。これを使ってmodel関数を色々いじり回して見ようと思います。