The Cookbook の CakePHP ブログチュートリアルを実践してみる(7)
10.1.9 記事の追加
Posts コントローラへの add() アクションの追加ですが、bake コマンドで既に生成されています。 チュートリアルのソースと bake で生成されたソースに若干の違いがあります。 bake で生成されたソースは $this->Session->setFlash() メソッドを利用して、遷移先の画面でメッセージを表示するようになっています。
10.1.10 データのバリデーション
Post モデルへのバリデーションの追加ですが、こちらも bake コマンドで既に生成されています。 チュートリアルでは minLength を指定し、必ず 1 文字以上の入力をさせようとしていますが、notempty を指定して、必須入力としたほうがわかりやすいのではと思います。
10.1.11 投稿記事の削除
Posts コントローラへの delete() アクションの追加ですが、こちらも bake コマンドで既に生成されています。 bake で生成されたソースは 引数が指定されていない場合、メッセージを表示するようになっています。
10.1.12 投稿記事の編集
Posts コントローラへの edit() アクションと edit ビューの追加ですが、こちらも bake コマンドで既に生成されています。 bake で生成されたソースは 引数、フォームデータが共に指定されていない場合、メッセージを表示するようになっています。
10.1.13 ルーティング(Routes)
以下の行をコメントアウトし、
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
以下の行を追加します。
Router::connect('/', array('controller' => 'posts', 'action' => 'index'));
これで、今までは http://localhost/cake_blog_tutorial/posts としてアクセスしていたところを http://localhost/cake_blog_tutorial/ でアクセスできるようになります。
10.1.14 まとめ
チュートリアルはこれで終わりです。
マニュアルの残り( http://book.cakephp.org/ja/ ) と APIリファレンス ( http://api.cakephp.org/classes ) を使って、自分のプロジェクトを始めよう! との事です。 訳文がおもしろいですね(笑)
The Cookbook の CakePHP ブログチュートリアルを実践してみる(6)
10.1.8 Postビューの作成
Posts コントローラに続いて Posts ビューを作成します。
ターミナルから以下のコマンドを実行します。
$ cd /Users/ryo/Sites/eclipse_workspace/cake_blog_tutorial/cake/console $ ./cake bake
以下の画面が表示されます。
Welcome to CakePHP v1.2.0.7962 Console --------------------------------------------------------------- App : app Path: /Users/ryo/Sites/eclipse_workspace/cake_blog_tutorial/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) > V
今回は View を生成したいので V を入力します。
以下の画面が表示されます。
-------------------------------------------------------------- Bake View Path: /Users/ryo/Sites/eclipse_workspace/cake_blog_tutorial/app/views/ --------------------------------------------------------------- Possible Controllers based on your current database: 1. Posts Enter a number from the list above, type in the name of another controller, or 'q' to exit [q] > 1
現在のデータベースから選択できるビューが一覧表示されます。
今回は posts テーブルから生成できる Posts ビューのみです。
1 を入力します。
以下の画面が表示されます。
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
index(一覧) , add(追加) , view(詳細) , edit(編集) といったビューを生成するか聞かれています。事前にコントローラとモデル(アソシエーションを設定している場合、設定した全てのモデル)を生成しておく必要があります。
y を入力します。
以下の画面が表示されます。
Would you like to create the methods for admin routing? (y/n) [n] > n
admin routing 用のメソッドを生成するか聞かれています。
n を入力します。
以下の画面が表示されます。
Creating file /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/app/views/posts/index.ctp Wrote /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/app/views/posts/index.ctp Creating file /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/app/views/posts/view.ctp Wrote /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/app/views/posts/view.ctp Creating file /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/app/views/posts/add.ctp Wrote /Users/ryo/Sites/eclipse_workspace/cake_blog_tutorial/app/views/posts/add.ctp Creating file /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/app/views/posts/edit.ctp Wrote /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/app/views/posts/edit.ctp --------------------------------------------------------------- View Scaffolding Complete. ---------------------------------------------------------------
もとの画面に戻ってくるので Q でBake をぬけます。
生成されたファイルは以下になります。
app/views/posts/index.ctp
<div class="posts index"> <h2><?php __('Posts');?></h2> <p> <?php echo $paginator->counter( array( 'format' => __('Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%', true) ) ); ?></p> <table cellpadding="0" cellspacing="0"> <tr> <th><?php echo $paginator->sort('id');?></th> <th><?php echo $paginator->sort('title');?></th> <th><?php echo $paginator->sort('body');?></th> <th><?php echo $paginator->sort('created');?></th> <th><?php echo $paginator->sort('modified');?></th> <th class="actions"><?php __('Actions');?></th> </tr> <?php $i = 0; foreach ($posts as $post) : $class = null; if ($i++ % 2 == 0) { $class = ' class="altrow"'; } ?> <tr<?php echo $class;?>> <td> <?php echo $post['Post']['id']; ?> </td> <td> <?php echo $post['Post']['title']; ?> </td> <td> <?php echo $post['Post']['body']; ?> </td> <td> <?php echo $post['Post']['created']; ?> </td> <td> <?php echo $post['Post']['modified']; ?> </td> <td class="actions"> <?php echo $html->link(__('View', true), array('action'=>'view', $post['Post']['id'])); ?> <?php echo $html->link(__('Edit', true), array('action'=>'edit', $post['Post']['id'])); ?> <?php echo $html->link(__('Delete', true), array('action'=>'delete', $post['Post']['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $post['Post']['id'])); ?> </td> </tr> <?php endforeach; ?> </table> </div> <div class="paging"> <?php echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled'));?> | <?php echo $paginator->numbers();?> <?php echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled'));?> </div> <div class="actions"> <ul> <li><?php echo $html->link(__('New Post', true), array('action'=>'add')); ?></li> </ul> </div>
app/views/posts/view.ctp
<div class="posts view"> <h2><?php __('Post');?></h2> <dl><?php $i = 0; $class = ' class="altrow"';?> <dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Id'); ?></dt> <dd<?php if ($i++ % 2 == 0) echo $class;?>> <?php echo $post['Post']['id']; ?> </dd> <dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Title'); ?></dt> <dd<?php if ($i++ % 2 == 0) echo $class;?>> <?php echo $post['Post']['title']; ?> </dd> <dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Body'); ?></dt> <dd<?php if ($i++ % 2 == 0) echo $class;?>> <?php echo $post['Post']['body']; ?> </dd> <dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Created'); ?></dt> <dd<?php if ($i++ % 2 == 0) echo $class;?>> <?php echo $post['Post']['created']; ?> </dd> <dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Modified'); ?></dt> <dd<?php if ($i++ % 2 == 0) echo $class;?>> <?php echo $post['Post']['modified']; ?> </dd> </dl> </div> <div class="actions"> <ul> <li><?php echo $html->link(__('Edit Post', true), array('action'=>'edit', $post['Post']['id'])); ?> </li> <li><?php echo $html->link(__('Delete Post', true), array('action'=>'delete', $post['Post']['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $post['Post']['id'])); ?> </li> <li><?php echo $html->link(__('List Posts', true), array('action'=>'index')); ?> </li> <li><?php echo $html->link(__('New Post', true), array('action'=>'add')); ?> </li> </ul> </div>
app/views/posts/add.ctp
<div class="posts form"> <?php echo $form->create('Post');?> <fieldset> <legend><?php __('Add Post');?></legend> <?php echo $form->input('title'); echo $form->input('body'); ?> </fieldset> <?php echo $form->end('Submit');?> </div> <div class="actions"> <ul> <li><?php echo $html->link(__('List Posts', true), array('action'=>'index'));?></li> </ul> </div>
app/views/posts/edit.ctp
<div class="posts form"> <?php echo $form->create('Post');?> <fieldset> <legend><?php __('Edit Post');?></legend> <?php echo $form->input('id'); echo $form->input('title'); echo $form->input('body'); ?> </fieldset> <?php echo $form->end('Submit');?> </div> <div class="actions"> <ul> <li><?php echo $html->link(__('Delete', true), array('action'=>'delete', $form->value('Post.id')), null, sprintf(__('Are you sure you want to delete # %s?', true), $form->value('Post.id'))); ?></li> <li><?php echo $html->link(__('List Posts', true), array('action'=>'index'));?></li> </ul> </div>
The Cookbook の CakePHP ブログチュートリアルを実践してみる(5)
10.1.7 Postsコントローラの作成
Post モデルに続いて Posts コントローラを作成します。
ターミナルから以下のコマンドを実行します。
$ cd /Users/ユーザ名/Sites/eclipse_workspace/cake_blog_tutorial/cake/console $ ./cake bake
以下の画面が表示されます。
Welcome to CakePHP v1.2.0.7962 Console --------------------------------------------------------------- App : app Path: /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/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) > C
今回はコントローラを生成したいので C を入力します。
以下の画面が表示されます。
--------------------------------------------------------------- Bake Controller Path: /Users/ryo/Sites/eclipse_workspace/cake_blog_tutorial/app/controllers/ --------------------------------------------------------------- Possible Controllers based on your current database: 1. Posts Enter a number from the list above, type in the name of another controller, or 'q' to exit [q] >
現在のデータベースから選択できるコントローラが一覧表示されます。
今回は posts テーブルから生成できる Posts コントローラのみです。
1 を入力します。
以下の画面が表示されます。
--------------------------------------------------------------- Baking PostsController --------------------------------------------------------------- Would you like to build your controller interactively? (y/n) [y] > y
対話形式でコントローラを作成するかと聞かれています。
y を入力します。
以下の画面が表示されます。
Would you like to use scaffolding? (y/n) [n] > n
scaffolding 機能を利用するかと聞かれています。
n を入力します。
以下の画面が表示されます。
Would you like to include some basic class methods (index(), add(), view(), edit())? (y/n) [n] > y
index(一覧) , add(追加) , view(詳細) , edit(編集) といった基本的なメソッドを生成するか聞かれています。
y を入力します。
以下の画面が表示されます。
Would you like to create the methods for admin routing? (y/n) [n] > n
admin routing 用のメソッドを生成するか聞かれています。
n を入力します。
以下の画面が表示されます。
Would you like this controller to use other helpers besides HtmlHelper and FormHelper? (y/n) [n] > n
HtmlHelper と FormHelper 以外のヘルパーを利用するか聞かれています。
n を入力します。
以下の画面が表示されます。
Would you like this controller to use any components? (y/n) [n] > n
何かコンポーネントを利用するか聞かれています。
n を入力します。
以下の画面が表示されます。
Would you like to use Sessions? (y/n) [y] > y
Session を利用するか聞かれています。
y を入力します。
以下の画面が表示されます。
--------------------------------------------------------------- The following controller will be created: --------------------------------------------------------------- Controller Name: Posts Notice: Undefined variable: helpers in /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/cake/console/libs/tasks/controller.php on line 195 Notice: Undefined variable: components in /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/cake/console/libs/tasks/controller.php on line 207 --------------------------------------------------------------- Look okay? (y/n) [y] > y
今まで設定したきた項目の確認です。
Notice は無視して構いません。
問題は無いので y を入力します。
以下の画面が表示されます。
Notice: Undefined variable: helpers in /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/cake/console/libs/tasks/controller.php on line 222 Notice: Undefined variable: components in /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/cake/console/libs/tasks/controller.php on line 222 Notice: Undefined variable: uses in /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/cake/console/libs/tasks/controller.php on line 222 Creating file /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/app/controllers/posts_controller.php Wrote /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/app/controllers/posts_controller.php Cake test suite not installed. Do you want to bake unit test files anyway? (y/n) [y] > n
ユニットテスト用のファイルを生成するかを聞いかれています。
今回は ユニットテスト用のファイルは生成しません。
n を入力します。
Notice は無視して構いません。
もとの画面に戻ってくるので Q でBake をぬけます
生成されたファイルは以下になります。
<?php class PostsController extends AppController { var $name = 'Posts'; var $helpers = array('Html', 'Form'); function index() { $this->Post->recursive = 0; $this->set('posts', $this->paginate()); } function view($id = null) { if (!$id) { $this->Session->setFlash(__('Invalid Post.', true)); $this->redirect(array('action'=>'index')); } $this->set('post', $this->Post->read(null, $id)); } function add() { if (!empty($this->data)) { $this->Post->create(); if ($this->Post->save($this->data)) { $this->Session->setFlash(__('The Post has been saved', true)); $this->redirect(array('action'=>'index')); } else { $this->Session->setFlash(__('The Post could not be saved. Please, try again.', true)); } } } function edit($id = null) { if (!$id && empty($this->data)) { $this->Session->setFlash(__('Invalid Post', true)); $this->redirect(array('action'=>'index')); } if (!empty($this->data)) { if ($this->Post->save($this->data)) { $this->Session->setFlash(__('The Post has been saved', true)); $this->redirect(array('action'=>'index')); } else { $this->Session->setFlash(__('The Post could not be saved. Please, try again.', true)); } } if (empty($this->data)) { $this->data = $this->Post->read(null, $id); } } function delete($id = null) { if (!$id) { $this->Session->setFlash(__('Invalid id for Post', true)); $this->redirect(array('action'=>'index')); } if ($this->Post->del($id)) { $this->Session->setFlash(__('Post deleted', true)); $this->redirect(array('action'=>'index')); } } } ?>
The Cookbook の CakePHP ブログチュートリアルを実践してみる(4)
10.1.6 Postモデルの作成
Bake を利用してコードの自動生成をしてみます。 Bake の本体は cake/console 内にあります。
実行権限が無いと Bake を実行できないので、chmod コマンドで実行権限をつけてから Bake を実行します。
ターミナルから以下のコマンドを入力します。
$ cd /Users/ユーザ名/Sites/eclipse_workspace/cake_blog_tutorial/cake/console $ chmod 755 cake $ ./cake bake
以下の画面が表示されます。
Welcome to CakePHP v1.2.0.7962 Console --------------------------------------------------------------- App : app Path: /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/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
Database Configuration はデータベースの接続情報の設定。 Model はモデルクラス。 View はビューファイル。 Controller はコントローラークラス。 Project はプロジェクトを、それぞれ生成します。 Quit は Bake を終了します。
今回はモデルクラスを生成したいので M を入力します。
以下の画面が表示されます。
--------------------------------------------------------------- Bake Model Path: /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/app/models/ --------------------------------------------------------------- Use Database Config: (default/test) [default] > default
database.php に設定したデータベースの接続情報のうち、どれを利用するかを入力します。
今回は default を利用するので default を入力 もしくは 何も入力しないで return キーを押します。
以下の画面が表示されます。
Possible Models based on your current database: 1. Post Enter a number from the list above, type in the name of another model, or 'q' to exit [q] > 1
現在のデータベースから選択できるモデルが一覧表示されます。
今回は posts テーブルから生成できる Post モデルのみです。
1 を入力します。
以下の画面が表示されます。
Would you like to supply validation criteria for the fields in your model? (y/n) [y] > y
バリデーションの定義をするかを聞かれています。
バリデーションの設定をするために y を入力 もしくは 何も入力しないで return キーを押します。
以下の画面が表示されます。
Field: id Type: integer --------------------------------------------------------------- Please select one of the following validation options: --------------------------------------------------------------- 1 - alphaNumeric 2 - between 3 - blank 4 - boolean 5 - cc 6 - comparison 7 - custom 8 - date 9 - decimal 10 - email 11 - equalTo 12 - extension 13 - file 14 - inList 15 - ip 16 - maxLength 17 - minLength 18 - money 19 - multiple 20 - notEmpty 21 - numeric 22 - phone 23 - postal 24 - range 25 - ssn 26 - time 27 - url 28 - userDefined 29 - Do not do any validation on this field. ... or enter in a valid regex validation string. [29] > 29
id フィールドに対してどのバリデーションを適用するかを聞かれています。
id フィールドにはバリデーションを設定したくないので 29 を入力します。
残りのフィールドに対してもバリデーションの設定がつづくので、title と body には 20 を入力し、必須入力にします。 created と modified には id 同様、バリデーションの必要は無いので 29 を入力します。
以下の画面が表示されます。
Would you like to define model associations (hasMany, hasOne, belongsTo, etc.)? (y/n) [y] > n
モデルのアソシエーションを定義するか聞かれています。
今回は 1 テーブルしかないので、アソシエーションの必要はありません。
n を入力します。
以下の画面が表示されます。
--------------------------------------------------------------- The following Model will be created: --------------------------------------------------------------- Name: Post Validation: Array ( [title] => notempty [body] => notempty ) Associations: --------------------------------------------------------------- Look okay? (y/n) [y] > y
今まで設定したきた項目の確認です。
問題は無いので y を入力します。
以下の画面が表示されます。
Baking model class for Post... Creating file /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/app/models/post.php Wrote /Users/*****/Sites/eclipse_workspace/cake_blog_tutorial/app/models/post.php Cake test suite not installed. Do you want to bake unit test files anyway? (y/n) [y] > n
ユニットテスト用のファイルを生成するかを聞いかれています。
今回は ユニットテスト用のファイルは生成しません。
n を入力します。
もとの画面に戻ってくるので Q でBake をぬけます
生成されたファイルは以下になります。
app/models/post.php
<?php class Post extends AppModel { var $name = 'Post'; var $validate = array( 'title' => array('notempty'), 'body' => array('notempty') ); } ?>
CakePHP : モデルとデータベースの規約
テーブルの命名規約
- テーブル名
- 複数形でアンダースコア記法。 persons , big_persons, really_big_persons など
- 主キー
- id という名前の整数型で、オートインクリメントを指定。複合主キーはサポートされていない
- 外部キー
- テーブル名の単数形_id という名前。 person_id , big_person_id , really_big_person_id など
- カラム名 ( name もしくは title )
- フィールドのラベルとして優先的に利用される
- カラム名 ( created )
- レコードが一番初めに追加されたときに、現在日時がセットされる。datetime 型を指定
- カラム名 ( modified もしくは updated )
- すでに存在するレコードが保存されたときに、現在日時で更新される。datetime 型を指定
モデルクラスの命名規約
単数形でキャメル記法。 Person、BigPerson、ReallyBigPerson など
The Cookbook の CakePHP ブログチュートリアルを実践してみる(3)
[ 10.1.4 追加の設定 ]
チュートリアルにある通り、ハッシュの生成に用いられる文字列を変更します。
[ 10.1.5 mod_rewriteについて ]
mod_rewrite の設定についてと、mod_rewrite を利用しない ( できない ) 場合についての記述があります。
mod_rewrite の設定はインストール時の手順で既に済ませてしまったので割愛します。
http://localhost/cake_blog_tutorial/ へアクセスしてみます。
設定に誤りがなければ CakePHP の初期画面が表示され、warningや notice 等の表示が無くなっているはずです。
また、以下の文言が表示されていれば、データベースへの接続が正常に行われています。
Your database configuration file is present. Cake is able to connect to the database.
The Cookbook の CakePHP ブログチュートリアルを実践してみる(2)
[ 10.1.3 Cakeのデータベース設定 ]
(1) で作成したデータベースへ、同じく (1) で作成したユーザで接続します。
データベース設定ファイル database.php を /app/config/database.php.default をコピーして作成します。
複数の接続情報を配列で記述する事ができますが、デフォルトで使用されるのは $default 配列なので、この配列の値を以下のように修正します。
/app/config/database.php
var $default = array( 'driver' => 'mysql', 'persistent' => false, 'host' => 'localhost', 'login' => 'cake_blog', 'password' => '12345', 'database' => 'cake_blog_tutorial', 'prefix' => '', 'port' => '', 'encoding' => 'utf8', 'schema' => '', );
設定用配列の各項目の詳細
- driver
- データベースのドライバ名。mysql, postgres, sqlite, pear-drivername, adodb-drivername, mssql, oracle, odbc など
- persistent
- 持続的接続(persistent connection)を使うかどうかを設定
- host
- データベースサーバのホスト名。(またはIPアドレス)
- login
- アカウントのユーザ名
- password
- アカウントのパスワード
- database
- この接続が利用するデータベース名
- prefix (オプション)
- データベース内のすべてのテーブルの頭に付ける接頭辞(prefix)。もしテーブルに接頭辞が付いていないのであれば指定しない
- schema
- PostgreSQLデータベースの設定時に、どのスキーマを使うかを指定