CakePHPで高速Webアプリ開発

仕事で勉強する必要に駆られたので、「CakePHPで高速Webアプリ開発」を基に勉強。
でも、例が1.1なんだけど使ってるのは1.2だったりして結構直しが必要だったのでメモ。
ちなみにMultiple flashes with different classesを使用してみた。エラーメッセージが綺麗に出力されて便利。
models/tasks.php

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

/*
 * 入力規則のチェック
 * http://www.syuhari.jp/blog/archives/394
 */
    var $validate =
        array("content" => array(
                "required" => array(
                    "rule"=>VALID_NOT_EMPTY ,
                    "message" => "必須項目です"
                    ),
                 ),
              );
}
?>

controllers/tasks_controller.php

<?php
// app/controllers/tasks_controller.php
class TasksController extends AppController {
    var $name = "Tasks";
    var $uses = array("Task");
    var $helpers = array("flash");

    var $app_title = "CakePHPでToDoアプリ!";

    /*
     * Multiple flashes with different classes
     * http://bakery.cakephp.org/articles/view/multiple-flashes-with-different-classes
     * flashヘルパを使用しています。
     */
    function flash( $message, $class = "status" ) {
        $this->Session->activate();
        $old = $this->Session->read("messages");
        $old[$class][] = $message;
        $this->Session->write( "messages", $old );
    }
   
    /* デフォルトで実行されるアクション */
    function index() {
        /* 未完了タスクのデータを取得する */
        $this->set("yet_tasks", $this->Task->findAllByStatus("yet", null, "Task.created ASC"));

        /* 完了タスクのデータを取得する */
        $this->set("done_tasks", $this->Task->findAllByStatus("done", null, "Task.modified DESC"));
        $this->pageTitle = $this->app_title . " - タスク一覧";
    }

    /* データ追加アクション */
    function add () {
        //データが渡っていれば
        if (!empty($this->data) && $this->data["Task"]["content"] != "") {
            //保存処理を実行する
            if ($this->Task->save($this->data, true, array("content", "created", "modified"))) {
                //画面にメッセージを表示
                $this->flash("追加したよ!", "success");
                /*
                 サンプルでは
                 $this->flash("タスクが追加されました", "/tasks");
                 してるけど、イマイチなのでしない!
                 */
            }
        }
        else {
            $this->flash("入力してよ!", "error");
        }
        $this->redirect("/tasks");
    }

    /* タスクを「完了」にした時のアクション */
    function done($id) {
        if ($this->Task->findById($id)) {
            $this->Task->id = $id;
            $this->Task->save(array("status" => "done"));
            $this->flash("完了にしたよ!", "success");
        }
        $this->redirect("/tasks");
    }

    /* タスク編集時のアクション */
    function edit($id) {
        /* idでデータを取得してみる */
        $task = $this->Task->findById($id);
        if (!$task) {
            /* 取得できなければリストページに戻す */
            $this->redirect("/tasks");
            return;
        }
        if (!empty($this->data)) {
            if ($this->data["Task"]["content"] != "") {
                /* オブジェクトへ値を格納してテーブルを更新する */
                $task["Task"]["content"] = $this->data["Task"]["content"];
                $this->Task->save($task);
                $this->flash("更新したよ!", "success");
            }
            else {
                $this->flash("入力してよ!", "error");
            }
        }
        $this->set("task", $task);
        $this->pageTitle = $this->app_title . " - タスクの編集 ID: " . $id;
    }

    /* タスク削除時のアクション */
    function del($id) {
        $this->Task->del($id);
        $this->flash("削除したよ!", "success");
        $this->redirect("/tasks");
    }
}
?>

views/tasks/index.ctp

<?php
/*
http://gihyo.jp/dev/serial/01/cakephp/0006
の記述方法で書くと、1.2ではうまく保存できなかった。以下の書き方なら大丈夫。
ちなみにこの書き方は、CakePHPポケットリファレンスを参照。
*/
/* フォームオブジェクト開始 */
echo $form->create("Task", array("action" => "add",
                                 "type"=>"post"));
/* contentに対応するテキストエリアを追加 */
echo $form->text("content", array("type"=>"text"));

/* フォームオブジェクト終了(submitボタンもついでに追加) */
echo $form->end(array("label" => "タスクを追加",
                      "name" => "submitButton",
                      "div" => array("class"=>"submitDiv")));
?>

<?php echo $flash->show(); ?>

<h2>未完了タスク</h2>
<table>
<tr>
<th>Id</th>
<th>タスク内容</th>
<th>状態</th>
<th>操作</th>
<th>作成日</th>
</tr>
<?php
/* オブジェクトの値をループ。イメージとしてはDAO? */
foreach ($yet_tasks as $task) { ?>
<tr>
<td><?php echo h($task["Task"]["id"]) ?></td>
<td><?php echo h($task["Task"]["content"]) ?></td>
<td><?php echo h($task["Task"]["status"]) ?></td>
<td>
 <?php echo $html->link("完了", "/tasks/done/" . $task["Task"]["id"], null, "完了してもよろしいですか?") ?>
<?php echo $html->link("編集", "/tasks/edit/" . $task["Task"]["id"]) ?>
<?php echo $html->link("削除",  "/tasks/del/"  . $task["Task"]["id"], null, "削除してもよろしいですか?") ?>
</td>
<td><?php echo h($task["Task"]["created"]) ?></td>
</tr>
<?php } ?>
</table>

<h2>完了タスク</h2>

<table>
<tr>
<th>Id</th>
<th>タスク内容</th>
<th>状態</th>
<th>操作</th>
<th>作成日</th>
</tr>
<?php foreach ($done_tasks as $task) { ?>
<tr>
<td><?php echo h($task["Task"]["id"]) ?></td>
<td><?php echo h($task["Task"]["content"]) ?></td>
<td><?php echo h($task["Task"]["status"]) ?></td>
<td><?php echo $html->link("削除", "/tasks/del/" . $task["Task"]["id"], null, "削除してもよろしいですか?") ?></td>
<td><?php echo h($task["Task"]["created"]) ?></td>
</tr>
<?php } ?>
</table>

views/tasks/edit.ctp

<h1>タスクの編集</h1>
<p><a href="<?php echo h($html->url("/tasks")) ?>">タスク一覧へ戻る</a></p>

<?php echo $flash->show(); ?>

<?php
/* フォームオブジェクト開始 */
echo $form->create("Task", array("action" => "edit/".$task["Task"]["id"],
                                 "type" => "post"));
/* idを隠しフィールドとして格納 */
echo $form->hidden("Task.id", array("value" => $task["Task"]["id"]));

/* contentに対応するテキストエリアを追加 */
echo $form->text("content", array("type" => "text",
                                   "value" => $task["Task"]["content"]));

/* フォームオブジェクト終了(submitボタンもついでに追加) */
echo $form->end(array("label" => "タスクを更新",
                      "name" => "submitButton",
                      "div" => array("class"=>"submitDiv")));
?>

views/layouts/default.ctp

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title><?php echo h($title_for_layout); ?></title>
<?php echo $html->css("cake.generic");?>
</head>
<body>
  <div id="container">
    <div id="header">
      <h1>Todo App</h1>
    </div>
    <div id="content">
      <?php echo $content_for_layout; ?>
    </div>
  </div>
</body>
</html>