『CakePHP』を使ってみる 〜9〜 『Cake ブログチュートリアル』を元に簡単なブログを作る

前回の続き。『Cake ブログチュートリアル』で作った Blog にコメント機能をつけてみる。

フォームのアクションで悩む

一般的なブログのように、エントリを 1件表示して、本文の下あたりにコメントがあったら一覧を表示。その下にコメントフォームという構成にしてみる。
まずは、コメントフォームを作ってみる。

コメントフォームを作る

まずここで悩んだ。アクションはどうするのが正しいのか?
Blogsコントローラ内にコメント追加用のメソッドを作るべきなのか?
その場合、編集機能をつけたりした時はどうしようとかいろいろ考えた結果、Comments コンローラを作ってそちらで処理することにしてみた。

『/home/theworld/cake/project/tutorial/views/blogs/entry.thtml』に以下を追加してみた。

<h2>Comments</h2>

<?php echo $form->create('Comment', array('action' => 'add'));?>
<?php echo $form->input('Comment.name', array('type' => 'text', 'size' => 40, 'error'=> array('required' => true, 'message'=> 'Input your name.')));?>
<?php echo $form->input('Comment.body', array('type' => 'textarea', 'cols' => 50, 'rows' => 10, 'error'=> array('required' => 'Input comment.')));?>
<?php echo $form->input('Comment.post_id', array('type' => 'hidden'));?>
<?php echo $form->submit('add comment');?>
<?php echo $form->end()?>

どのエントリに対するコメントかわかるように、hidden に post_id を埋めておいた。
hidden に値をするための処理を entryメソッドに追加しておく。

function entry($id)
{
	$post = $this->Post->findById($id);
	$this->postTitle = h($post['Post']['title']);
	$this->set('post', $post);
	$this->data['Comment']['post_id'] = $post['Post']['id']; //コレ
}
Comment モデルを作る

『/home/theworld/cake/project/tutorial/models/comment.php』にモデルを追加した。

<?php
class Comment extends AppModel
{
	var $name = "Comment";

	var $validate = array(
			'name' => array(
				'required' => VALID_NOT_EMPTY
			),
			'body' => array(
				'required' => VALID_NOT_EMPTY
			),
		);
}
?>

name と body を必須入力とするようにしておいた。
練習なのでデータチェックはとりあえずこのくらいで。

Comments コントローラを作る

『/home/theworld/cake/project/tutorial/controllers/comments_controller.php』を作る。

<?php
class CommentsController extends AppController
{
	var $name = 'Comments';
	
	function add()
	{
		if(!empty($this->data['Comment']))
		{
			if($this->Comment->save($this->data))
			{
				$this->flash('Your post has been saved', '/blogs/entry/'.$this->data['Comment']['post_id'].'/s');
			}
		}
	}
}
?>

データが投げられていたら保存する add メソッドを作成した。

Comment ビューを作る

『/home/theworld/cake/project/tutorial/views/comments/add.thtml』を作成。
入力エラーがあった場合に表示されるページ。
entry の下部につけたフォームと同じようなもの。かぶっていてなんかムダっぽい。
どうするのが正しいのだろう?

<h2>Comments</h2>

<?php echo $form->create('Comment', array('action' => 'add/'));?>
<?php echo $form->input('Comment.name', array(
							'type' => 'text', 
							'size' => 40, 
							'error'=> array(
								'required' => 'Input your name.'
							)
						)
					);?>
<?php echo $form->input('Comment.body', array(
							'type' => 'textarea', 
							'cols' => 50, 'rows' => 10, 
							'error'=> array(
								'required' => 'Input your comment.'
							)
						)
					);?>
<?php echo $form->input('Comment.post_id', array('type' => 'hidden'));?>
<?php echo $form->submit('add comment');?>
<?php echo $form->end()?>

エラーがあった場合にメッセージが出るように。

両方入力した場合はちゃんとコメントが保存できるようになった。

コメント一覧を表示させる

アソシエーションの設定

Post モデル『/home/theworld/cake/project/tutorial/models/post.php』にアソシエーションの設定をする。
エントリに対するコメントのような場合は $hasMany を使うらしい。
他にも $hasOne とか $belongTo とかあるけど、どれを使うべきかという判断がつかなかったりするので後でちゃんと確認する。

<?php
class Post extends AppModel
{
	var $name = "Post";
	var $validate = array(
			'title' => array('required' => VALID_NOT_EMPTY),
			'body' => array('required' => VALID_NOT_EMPTY),
	);

	var $hasMany = array(
			'Comment' => array(
				'className' => 'Comment',
				'conditions' => '',
				'order' => '',
				'dependent' => true,
				'foreignKey' => 'post_id',
			)
		);
}
?>

これで、コントローラでデータを呼び出すと自動的にコメントデータもとれるようになった。

$post = $this->Post->findById($id);
pr($post)

以下のようにデータがとれる。

Array
(
    [Post] => Array
        (
            [id] => 1
            [title] => The title
            [body] => This is the post body.
            [created] => 2008-02-27 11:21:08
            [modified] => 
        )

    [Comment] => Array
        (
            [0] => Array
                (
                    [id] => 1
                    [name] => theworldjp
                    [post_id] => 1
                    [body] => comment
                    [created] => 2008-03-04 22:36:18
                    [modified] => 2008-03-04 22:36:18
                )

            [1] => Array
                (
                    [id] => 2
                    [name] => Yossy
                    [post_id] => 1
                    [body] => てすと
します
                    [created] => 2008-03-04 22:56:19
                    [modified] => 2008-03-04 22:56:19
                )

            [2] => Array
                (
                    [id] => 3
                    [name] => よっしー<xmp>
                    [post_id] => 1
                    [body] => あんぐら
<xmp>
                    [created] => 2008-03-04 22:59:59
                    [modified] => 2008-03-04 22:59:59
                )

        )

)
ビューにコメント一覧を表示させる記述を追加

『/home/theworld/cake/project/tutorial/views/blogs/entry.thtml』に以下を追加。

<h2>Comments</h2>

<?php foreach($post['Comment'] as $comment){ ?>
<p><?=h($comment['created'])?> | Posted  by <?=h($comment['name'])?></p>
<p style="padding-bottom: 1em"><?=h($comment['body'])?></p>
<?php } ?>

エントリにアクセスしてみる。
http://lab.theworld.jp/cakephp/tutorial/blogs/entry/1/


うまくいった!これは便利!
次は何を作ろう。タグとか?