簡単なアプリをとりあえず

前回インストールとDB接続の確認までしたのでCakePHP簡単なアプリを作ってみました。カテゴリー別の掲示版のようなものですが、とりあえず、そのカテゴリーの表示、編集部分です。(前のも似たことをやったけど忘れかけているので復習です)。

テーブル

今回、カテゴリーテーブルを以下のように作成しました。

CREATE TABLE IF NOT EXISTS `categories` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(64) NOT NULL,
  `description` varchar(4096) default NULL,
  `user_id` int(11) NOT NULL,
  `created` datetime default NULL,
  `updated` datetime default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
    1. user_idは、作成ユーザを設定する意図で作成しています。今回はまだ実装しませんが。。

bakeでController,Model,Viewを生成

管理コマンドで、カテゴリーに対するController,Model,Viewのテンプレートを作ります。アプリケーションのトップの位置から以下の対話インターフェイスの一覧で作成しました。

nyaago@kyonkyon: 528 /Users/nyaago/workspace/cakeboard$php ./cake/console/cake.php bake

Welcome to CakePHP v1.2.0.7296 RC2 Console
---------------------------------------------------------------
App : app
Path: /Users/nyaago/workspace/cakeboard/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: /Users/nyaago/workspace/cakeboard/app/models/
---------------------------------------------------------------
Use Database Config: (default/test) 
[default] > 
Possible Models based on your current database:
1. Article
2. Category
3. LoginHistory
4. Topic
5. UserCategory
6. User
Enter a number from the list above, type in the name of another model, or 'q' to exit  
[q] > 2
Would you like to supply validation criteria for the fields in your model? (y/n) 
[y] > y

Field: id
Type: integer
---------------------------------------------------------------
Please select one of the following validation options:
---------------------------------------------------------------
1 - alphaNumeric
2 - between
3 - blank

... このあたり省略...
  
[28] > 
Would you like to define model associations (hasMany, hasOne, belongsTo, etc.)? (y/n) 
[y] > 
One moment while the associations are detected.
---------------------------------------------------------------
Please confirm the following associations:
---------------------------------------------------------------
Category belongsTo User? (y/n) 
[y] > n
Category hasOne Topic? (y/n) 
[y] > n
Category hasMany Topic? (y/n) 
[y] > n
Category hasAndBelongsToMany User? (y/n) 
[y] > n
Would you like to define some additional model associations? (y/n) 
[n] > 

---------------------------------------------------------------
The following Model will be created:
---------------------------------------------------------------
Name:       Category
Validation: Array
(
    [name] => 3 16
    [description] => maxlength
)

Associations:
---------------------------------------------------------------
Look okay? (y/n) 
[y] > y

Baking model class for Category...

Creating file /Users/nyaago/workspace/cakeboard/app/models/category.php
Wrote /Users/nyaago/workspace/cakeboard/app/models/category.php
Cake test suite not installed.  Do you want to bake unit test files anyway? (y/n) 
[y] > 

You can download the Cake test suite from http://cakeforge.org/projects/testsuite/

Baking test fixture for Category...

Creating file /Users/nyaago/workspace/cakeboard/app/tests/fixtures/category_fixture.php
Wrote /Users/nyaago/workspace/cakeboard/app/tests/fixtures/category_fixture.php

Baking unit test for Category...

Creating file /Users/nyaago/workspace/cakeboard/app/tests/cases/models/category.test.php
Wrote /Users/nyaago/workspace/cakeboard/app/tests/cases/models/category.test.php
---------------------------------------------------------------
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) 
> C
---------------------------------------------------------------
Bake Controller
Path: /Users/nyaago/workspace/cakeboard/app/controllers/
---------------------------------------------------------------
Possible Controllers based on your current database:
1. Articles
2. Categories
3. LoginHistories
4. Topics
5. UserCategories
6. Users
Enter a number from the list above, type in the name of another controller, or 'q' to exit  
[q] > 2
---------------------------------------------------------------
Baking CategoriesController
---------------------------------------------------------------
Would you like to build your controller interactively? (y/n) 
[y] > 
Would you like to use scaffolding? (y/n) 
[n] > n
Would you like to include some basic class methods (index(), add(), view(), edit())? (y/n) 
[n] > y
Would you like to create the methods for admin routing? (y/n) 
[n] > n
Would you like this controller to use other helpers besides HtmlHelper and FormHelper? (y/n) 
[n] > n
Would you like this controller to use any components? (y/n) 
[n] > n
Would you like to use Sessions? (y/n) 
[y] > n


---------------------------------------------------------------
The following controller will be created:
---------------------------------------------------------------
Controller Name:  Categories
		   var $scaffold;
---------------------------------------------------------------
Look okay? (y/n) 
[y] > 

Creating file /Users/nyaago/workspace/cakeboard/app/controllers/categories_controller.php
Wrote /Users/nyaago/workspace/cakeboard/app/controllers/categories_controller.php
Cake test suite not installed.  Do you want to bake unit test files anyway? (y/n) 
[y] > 

You can download the Cake test suite from http://cakeforge.org/projects/testsuite/

Baking unit test for Categories...

Creating file /Users/nyaago/workspace/cakeboard/app/tests/cases/controllers/categories_controller.test.php
Wrote /Users/nyaago/workspace/cakeboard/app/tests/cases/controllers/categories_controller.test.php
---------------------------------------------------------------
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) 
> V
---------------------------------------------------------------
Bake View
Path: /Users/nyaago/workspace/cakeboard/app/views/
---------------------------------------------------------------
Possible Controllers based on your current database:
1. Articles
2. Categories
3. LoginHistories
4. Topics
5. UserCategories
6. Users
Enter a number from the list above, type in the name of another controller, or 'q' to exit  
[q] > 2
Would you like to create some scaffolded views (index, add, view, edit) for this controller?
NOTE: Before doing so, you'll need to create your controller and model classes (including associated models). (y/n) 
[n] > y
Would you like to create the views for admin routing? (y/n) 
[y] > n

Creating file /Users/nyaago/workspace/cakeboard/app/views/categories/index.ctp
Wrote /Users/nyaago/workspace/cakeboard/app/views/categories/index.ctp

Creating file /Users/nyaago/workspace/cakeboard/app/views/categories/view.ctp
Wrote /Users/nyaago/workspace/cakeboard/app/views/categories/view.ctp

Creating file /Users/nyaago/workspace/cakeboard/app/views/categories/add.ctp
Wrote /Users/nyaago/workspace/cakeboard/app/views/categories/add.ctp

Creating file /Users/nyaago/workspace/cakeboard/app/views/categories/edit.ctp
Wrote /Users/nyaago/workspace/cakeboard/app/views/categories/edit.ctp
---------------------------------------------------------------

View Scaffolding Complete.

---------------------------------------------------------------
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) 
> 
    1. Scaffoldは使用しないよう指定して作成しました。
    2. Validationの指定もしたのですが(上の出力例から省略しています)、うまくコードができていませんでしたので、後でコード修正しました。

モデルの修正

Categoryのモデルを修正。Validationの指定を行いました。

<?php
class Category extends AppModel {

	var $name = 'Category';
	var $validate = array(
		'name' => array('rule' => VALID_NOT_EMPTY,
			'message' => 'いれて。')
		
		'description' =>  array(
			'rulename1' =>
			array('rule' => array( 'maxlength', 200),
				'message' => '半角で200,全角100文字以下にしてください。'
			),
			'rulename2' =>
			array('rule' => VALID_NOT_EMPTY,
				'message' => 'いれて。'
			)
		)
		
	);
}
?>
    1. 連想配列である$validate変数に各カラムの検証条件を指定していきます。配列の1要素がカラム名をキーとした検証条件になっています。値が条件ですが、検証条件が複数の場合は、検証ルール名をキーとする連想配列となっています。

なお、ここは、和訳ドキュメントの4.1 データのバリデーション(Data Validation)を参考にしました。

コントローラ(controler/CategoryController.php)

index(一覧)、view(詳細表示),edit(編集),add(追加),deleteのアクションが自動的に作成されています。一部変更して以下のようにしました。

<?php
class CategoriesController extends AppController {

	var $name = 'Categories';

    function index() {
        $this->Category->recursive = 0;
        $order = 'Category.created';
        if(!empty($this->params['named']['sort'])) {
            $order = $this->params['named']['sort'];
        }
        $this->paginate = array(
                'conditions' => array(),
                'order'  => $order,
                'limit' => 3,
            );
        $this->set('categories', $this->paginate('Category'));
    }

    function view($id = null) {
        if (!$id) {
            $this->Session->setFlash(__('Invalid Category.', true));
            $this->redirect(array('action'=>'index'));
        }
        $category = $this->Category->read(null, $id);
        if(!$category) {
            $this->Session->setFlash(__('存在しないカテゴリーです.', true));
            $this->redirect(array('action'=>'index'));
        }
        $this->set('category', $this->Category->read(null, $id));
    }

    function add() {
        if (!empty($this->data)) {  // 保存
            $this->Category->create();
            if ($this->Category->save($this->data)) {
                $this->Session->setFlash(__('The Category has been saved', true));
                $this->redirect(array('action'=>'index'));
            } else {
                $this->Session->setFlash(
					__('The Category could not be saved. Please, try again.', true));
            }
        }
    }

    function edit($id = null) {
        if (!$id && empty($this->data)) {
            $this->Session->setFlash(__('Invalid Category', true));
            $this->redirect(array('action'=>'index'));
        }
        if (!empty($this->data)) {
            if ($this->Category->save($this->data)) {
                $this->Session->setFlash(__('The Category has been saved', true));
                $this->redirect(array('action'=>'index'));
            } else {
                $this->Session->setFlash(
					__('The Category could not be saved. Please, try again.', true));
            }
        }
        if (empty($this->data)) {
            $this->data = $this->Category->read(null, $id);
        }
    }

    function delete($id = null) {
        if (!$id) {
            $this->Session->setFlash(__('Invalid id for Category', true));
            $this->redirect(array('action'=>'index'));
        }
        if ($this->Category->del($id)) {
            $this->Session->setFlash(__('Category deleted', true));
            $this->redirect(array('action'=>'index'));
        }
        else {
            $this->Session->setFlash(
                __('The Category could not be deleted. Please, try again.', true));

            $this->redirect(
                array('action'=>'index'));
        }
    }
}
?>
    1. cakephpでの標準のルーティングでは「//」というurlがコントローラー、アクションが対応するかたちとなります。そのため上記のCategoyコントローラーのindexアクションメソッドは「/categories/index」というurlで起動されることになります。
    2. indexアクションは一覧表示になっています。paginate属性に検索条件、1回の表示を設定して後、モデル名を指定して、paginateメソッド実行してページング情報を含む一覧情報を取得しています。取得した情報はsetメソッドによりviewに渡します。
    3. editアクションは、編集ページへの遷移と編集内容の保存を兼ねています。Postでデータが送信された場合、data属性に連想配列として送信データが含まれているので、その場合は保存処理をして、一覧ページへのリダイレクトという処理を行っています。
    4. addアクションは、新規編集ページへの遷移と編集内容の保存を兼ねています。
    5. viewアクションは、詳細表示です。モデルのreadメソッドにより表示データを取得しています。
    6. deleteアクションは、削除です。

View

とりあえず、bakeで自動生成したままです。

これで、とりあえず、一覧表示、詳細表示、追加、変更ができるようになりました。