CakePHPで掲示板を作る 2日目

さて、前日に引き続きRoRの方はちょっとお休みして、同じ内容をCakePHPでも作ってみようと思う。

残タスクの確認

  1. 新しい記事が上に来るように表示する
  2. インターフェイスの日本語化
  3. デザインの変更

新しい記事が上に来るように表示する

scaffold(ing)のままでは対応できない様子…

さて、RoRのscaffold同様データベースからレコードを取得してくる部分でorderを指定してやれば新着順で取得できるだろうと考え、articles_controller.phpを開いてみたのだがそこには

var $scaffold

という記載があるだけで、実際のscaffoldのCRUDのメソッドが記載されているわけではなかった。
CakePHPのドキュメントを読んでみたところ、どうやらCakePHPのscaffoldingの場合はあまり細かく動作をカスタマイズすることができないようだ。

今度はscaffoldを使用せずにbake

では、CRUDのメソッドを手動で書かなければいけないのか、といわれればそうではない。
bakeでMVCを作成する際、「scaffoldを使わない」を選択してもその後のウィザードでCRUDの各メソッドを作成してくれるのである。

本来であれば、ここで再度bakeでコードを生成して上書きするのはやはりあまりよろしくないが、まあ今回は初回だし目を瞑ろう…。

Controllerの再生成

まずはbakeを起動する

php cake/scripts/bake.php

データ構造が変わるわけではないので、今回はモデルは再生性しなくてよいので、「C」Controllerから生成する。
もちろん、対象のテーブルはArticles。

Would you like ... interactively?

は「y」としておくが

Would you like to use scaffolding?

は今回は「n」とする。

すると

Would you like to include some basic class methods?

と聞いてくるので、ここで「y」を選ぶとscaffolding同様、CRUDのメソッドが生成される。
admin routingと他のモデル・ヘルパー・コンポーネントを使うかの質問は「n」でスキップする。

Would you like to use Sessions?

は後々のことを考え「y」にしておこう。

確認画面がでるので、内容を確認して「y」を押す。
上書き確認がでるので「y」で進む。
前回同様、テストは「n」でスキップ。

ModelとViewは再生成しなくてよい

今回はデータ構造が変わっているわけではないので、モデルは再生成する必要がない。
また、コントローラの機能自体はscaffoldingと変わっていないので、ビューも再生成する必要はない。

表示順を変更する

そこで再びarticles_controller.phpを開いてみると、今度はメソッドがRoRの時同様定義されている。

	function index() {
		$this->Article->recursive = 0;
		$this->set('articles', $this->Article->findAll());
	}

リスト表示しているメソッドはこのindexである。
ドキュメントを読んだところ、この$this->Article->findAll()に引数を与えることで発行するSQLを操作できるようだ。
特に三番目の引数がorderの部分の指定になるので、ここを

		$this->set('articles', $this->Article->findAll(null,null,"id desc"));

としてみたところ、投稿降順で表示された。

日本語化する

さあ、ここまでくればもう多分一切説明はいらないでしょう。
(いままでも割りと書いてきたのは手順だけですが)

CakePHPのViewのテンプレートはapp/viewsディレクトリにある。
Articlesのインデックス(リスト表示)のテンプレートはapp/views/articles/index.thtml。
開いてみればもう一目瞭然、RoRのscaffoldのテンプレートとほとんど同じ。
なので、早速日本語化してみた。

<div class="articles">
<h2>掲示板</h2>
<ul class="actions">
	<li><?php echo $html->link('新規投稿', '/articles/add'); ?></li>
</ul>
<table cellpadding="0" cellspacing="0">
<tr>
	<th>Id</th>
	<th>Modified</th>
	<th>Name</th>
	<th>Title</th>
	<th>Body</th>
	<th>Actions</th>
</tr>
<?php foreach ($articles as $article): ?>
<tr>
	<td><?php echo $article['Article']['id']; ?></td>
	<td><?php echo $article['Article']['modified']; ?></td>
	<td><?php echo $article['Article']['name']; ?></td>
	<td><?php echo $article['Article']['title']; ?></td>
	<td><?php echo $article['Article']['body']; ?></td>
	<td class="actions">
		<?php echo $html->link('表示','/articles/view/' . $article['Article']['id'])?>
		<?php echo $html->link('編集','/articles/edit/' . $article['Article']['id'])?>
		<?php echo $html->link('削除','/articles/delete/' . $article['Article']['id'], null, '削除しますか?')?>
	</td>
</tr>
<?php endforeach; ?>
</table>


</div>

さて、気になる文字コードですが、ここではSJISでやったらうまくいったた。
CakePHPの日本語対応については、まだあまり情報にありつけてないので、後ほどまた調べようかと思う。


デザインを変える

さあ、段々と面倒くさくなってきた。
コーディングが面倒くさいのではなくて、RoRと同じ内容を再び繰り返すのが面倒になってきた。
ので、ここではもういきなりコードをのせてしまおう。
メソッドの記法がRubyからPHPに変わっている以外は、RoR編とほとんど同じです。

index.thtml
<div class="articles">
<h1>掲示板</h1>
<?php echo $html->link('新規投稿', '/articles/add'); ?>

<?php foreach ($articles as $article): ?>
 <div class="article">
  <h3><?php echo $article['Article']['title']; ?></h3>
  <span class="name"><?php echo $article['Article']['name']; ?></span>
  <span class="updated_at"><?php echo $article['Article']['modified']; ?></span>
  <p><?php echo $article['Article']['body']; ?></p>
  <ul>
   <li><?php echo $html->link('表示','/articles/view/' . $article['Article']['id'])?></li>
   <li><?php echo $html->link('編集','/articles/edit/' . $article['Article']['id'])?></li>
   <li><?php echo $html->link('削除','/articles/delete/' . $article['Article']['id'], null, '削除しますか?')?></li>
  </ul>
 </div>
<?php endforeach; ?>
</div>

スタイルシートはこちらはapp/webroot/cssディレクトリにある。

cake.generic.css

これに以下を追加した。

body {
	background-color: #eee; color: #333;
	text-align : center;
}
div.article{
	background-color : #fff;
	border : 2px solid #888;
	margin : 30px;
	text-align : left;
}
div.article h3{
	background-color : #666;
	color : #fff;
	padding : 0px;
	line-height : 30px;
	height : 30px;
	font-size : 14pt;
	margin : 0px;
}
div.article p{
	padding : 20px;
}
div.article ul{
	list-style : none;
	height : 30px;
}
div.article ul li{
	float : left;
	margin-right : 20px;
}