CakePHPで高速Webアプリ開発

第5回CakePHPで作るToDoアプリ(1)

第4回ではCakePHPでの開発環境を構築しました。今回からアプリケーション部分の開発にとりかかります。

開発するのはToDo管理アプリケーションです。今回は以下の作業を行います。

  • DBの設計と作成
  • コントローラの作成
  • モデルの作成
  • ビューの作成

この作業で実装される機能は以下になります。

  • タスク一覧の表示

このアプリケーション開発の前提として、DocumentRootは/home/gihyo/public_htmlで、URLはhttp://example.com/~gihyo/、CakePHPをセットアップしたディレクトリは/home/gihyo/public_html/todo、URLはhttp://example.com/~gihyo/todo/とします。

DBの設計と作成

まずはCakePHPに慣れるためのサンプルアプリケーションですので、機能は最小限とします。アプリケーションを利用する想定ユーザは1人だけとして、複数ユーザでの利用はとりあえずは想定外とします。

データベース名はtodo、タスクを管理するテーブル名はtasksとしました。テストデータを含むMySQL用のdumpが以下になります。

CREATE DATABASE todo;
use todo;
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
CREATE TABLE `tasks` (
  `id` int(11) unsigned NOT NULL auto_increment,
  `content` text NOT NULL,
  `status` enum('yet','done') NOT NULL default 'yet',
  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `status` (`status`),
  KEY `created` (`created`),
  KEY `modified` (`modified`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
INSERT INTO `tasks` (`id`, `content`, `status`, `created`, `modified`) VALUES 
(1, 'プログラマーズリファレンスガイドを一通り読む', 'done', '2007-08-20 00:00:00', '2007-08-21 01:00:00'),
(2, 'ブログチュートリアルを行う', 'yet', '2007-08-21 02:00:00', '2007-08-21 02:00:00'),
(3, 'CakePHP情報サイトをRSSリーダーに登録する', 'yet', '2007-08-21 05:00:00', '2007-08-21 05:00:00');

データベース名に合わせてapp/config/database.phpも書き換えますリスト1⁠。

リスト1 app/config/database.phpの書き換え

<?php
class DATABASE_CONFIG {
  var $default = array(
    'driver' => 'mysql',
    'connect' => 'mysql_connect',
    'host' => 'localhost',
    'login' => 'ここにDBのユーザー名',
    'password' => 'ここにDBのパスワード',
    'database' => 'todo',
    'prefix' => '',
  );
}

レンタルサーバなどでdb名が固定の場合は、それにあわせて変更してください。

tasksテーブルの解説

テーブル名は複数形

CakePHPの規約ではテーブル名は複数形です。この規約は絶対ではありませんが、規約から外れた場合は規約外であることを明示するコードを書き足す必要があるため、特別な理由がない限りは規約に沿っておくべきです。

複数形は単純に「s」が足されるわけではなく、英語として正しい複数形である必要があります。たとえばdiaryはdiariesとなります。

複数形がない単語は例外的にそのままになります。たとえば「news」などはテーブル名も「news」です。

プライマリキーはid

プライマリキーはidです。CakePHPの規約ではプライマリキーのフィールド名はidなので、新規開発時にはプライマリキーは必ずidとしておいたほうが良いでしょう。テーブル名と同様に規約外でも可能ですが、コードを書き足す必要があります。

タスク内容とステータス

タスク内容はcontentフィールドに入ります。タスクの状態は「未完了」⁠完了」の2つとして、enum型のstatusフィールドで「yet(まだ⁠⁠done(完了⁠⁠」で表現します。

作成日はcreated、更新日はmodified

タスクを作成した日はcreatedフィールドにdatetime型で入ります。更新日はmodifiedフィールドで、同様にdatetime型です。この2つのフィールド名はCakePHPの規約に沿っており、新規にレコードを作成したときやレコード内容を更新したときに自動で更新されます。何かと便利なフィールドですので、特別な理由がない限りは作成しておくと良いでしょう。

コントローラの作成

コントローラ名は基本的に自由です。今回必要なのはタスク一覧を表示するコントローラーなので、コントローラ名はtasksとします。コントローラはapp/controllers/コントローラ名_controller.phpファイルに書きます。

タスク一覧表示に必要なコードを含んだコントローラがリスト2になります。

リスト2 コントローラ

<?php
// app/controllers/tasks_controller.php
class TasksController extends AppController {
  var $name = 'Tasks';
  var $uses = array('Task');
  function index() {
    $this->set('tasks', $this->Task->findAll(null, null, 'Task.created ASC'));
  }
}

1行ずつ解説します。

class定義

class TasksController extends AppController {

コントローラはPHPのクラスで、必ずAppControllerを継承させます。

var $name = 'Tasks';

⁠var $name」には、単語の頭文字が大文字のコントローラ名を定義します。

使用するモデルの定義

var $uses = array('Task');

⁠var $uses」には、コントローラで使用するモデルを定義します(モデルそのものについては後述します⁠⁠。

ちなみにCakePHPでは$usesを書かなくてもコントローラ名の単数形のモデルを自動で読み込む機能があります。tasksコントローラではTaskモデルになるので、実はこの記述は冗長といえます。しかし実際のアプリケーション開発ではコントローラ名に紐付いたモデルだけでは足りないことが多いので、より実践的なサンプルとしてあえて$usesで定義しました。個人的には自動で読み込む機能は半分忘れてしまってもよいのではないかと思います。

複数のモデルを使用したいときは単純に配列として複数列挙します。たとえばTaskモデルとExampleモデルを使用したいときは、

var $uses = array('Task', 'Example');

となります。

アクションの定義

function index() {
  $this->set('tasks', $this->Task->findAll(null, null, 'Task.created ASC'));
}

コントローラのアクションは、コントローラクラスのメソッドとして登録します。アクションへのURLは「/コントローラ名/アクション名」となります。アクション名を付けずにアクセスしたときは、デフォルト状態ではindexアクションが呼ばれます。

URLからアクセスできないメソッドを作成したいときは、メソッド名の先頭に「_(アンダースコア⁠⁠」を付けます。アンダースコアを付けずに作成したメソッドはすべてURLからアクセスできてしまうので、セキュリティーホールの原因になる可能性があります。アクションとして使用しないメソッドには必ずアンダースコアを付けておきましょう。

アクションの内容

$this->set('tasks', $this->Task->findAll(null, null, 'Task.created ASC'));

この行ではtasksテーブルから作成日順にデータを取得し、tasksという変数名でビューに渡しています。

$this->set() はビューに値を渡すメソッドです。引数は (変数名, 値)です。

$this->Task->findAll()は、Taskモデルからデータを取得しています。引数は (検索条件, 取得フィールド, ソート条件, etc...) です。検索条件がnullの場合はすべて、取得フィールドもnullの場合は同じくすべて取得します。

ソート条件はMySQLのOrder句の要領で記述します。条件は「モデル名.フィールド名 順序」で記述し、複数記述する際はカンマ区切りで記述します。たとえばstatusの降順でcreatedの昇順の際は「Task.status DESC, Task.created ASC」となります。

モデル作成前に実行してみる

コントローラが作成できたら、とりあえず実行してみましょう。/~gihyo/todo/tasks を開きます。

モデル作成前では、図1のような画面が表示されます。

図1 モデル作成前の画面

図1 モデル作成前の画面

画面の後半にモデルの作成場所と、雛形が表示されています。実際の開発時で「あれっ? モデルは作成してあるのに」と思ったときはこのエラー画面と比較してスペルミスなどを確認すると良いでしょう。

次にモデルの作成を行います。

モデルの作成

CakePHPではDBへのアクセスはモデルを通して行います。モデルの定義は app/models/テーブル名の単数形.php ファイルに書きます。 tasksテーブルのモデルを定義するため、app/model/task.phpファイルを作成しますリスト3⁠。

リスト3 app/model/task.php

<?php
// app/model/task.php
class Task extends AppModel {
  var $name = 'Task';
}

モデルの定義はPHPのクラスで、必ずAppModelクラスを継承させます。⁠var $name」には単語の頭文字が大文字のモデル名を定義します。

モデルを作成したらもう一度/~gihyo/todo/tasksを開いてみましょう。

今度はビューが見つからないときのエラー画面が表示されました図2⁠。

図2 ビュー作成前のエラー画面

図2 ビュー作成前のエラー画面

次にビューの作成を行います。

ビューの作成

ビューは app/views/コントローラ名/自由なファイル名.thtml となります。ファイル名の部分をアクション名と同じにしておくとコントローラ側で明示する必要がなくなるので、1アクションにつき1テンプレートの場合は同じにしておくと良いでしょう。

tasksコントローラのindexアクション用のビューなので、app/views/tasks/index.thtmlを作成しますリスト4⁠。

リスト4 app/views/tasks/index.thtml

<table>
<tr>
<th>Id</th>
<th>タスク内容</th>
<th>状態</th>
<th>作成日</th>
</tr>
<?php foreach ($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 h($task['Task']['created']) ?></td>
</tr>
<?php } ?>
</table>

/~gihyo/todo/tasks を開いてみましょう。図3のような画面が表示されたら、今回の作業は終了です。

図3 コントローラ/モデル/ビュー作成後の画面

図3 コントローラ/モデル/ビュー作成後の画面

まずはお疲れ様でした。

最初は前提知識がないため戸惑う部分が多かったかと思います。フレームワークの習得速度は慣れればなれるほど上がっていくものですので、最初の戸惑いに負けずに取り組んでみてください。CakePHPは一般的なフレームワークに比べて覚えることが少ないので、何がわからないかがわからない状態から抜け出せるまでの期間は比較的短いと思います。

次回予定はタスク作成の開発です。

おすすめ記事

記事・ニュース一覧