nirasan's tech blog

趣味や仕事の覚え書きです。Linux, Perl, PHP, Ruby, Javascript, Android, Cocos2d-x, Unity などに興味があります。

CakePHPチュートリアルメモ

はじめに

インストール

チェックアウト

  • githubからCakePHPをチェックアウト
git clone git://github.com/cakephp/cakephp.git cakeblog

データベースの作成

  • CakePHP用のデータベースを作成
mysqladmin create cakeblog
  • ブログ記事を扱うpostsテーブルを作成する
mysql cakeblog
CREATE TABLE posts (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(50),
    body TEXT,
    created DATETIME DEFAULT NULL,
    modified DATETIME DEFAULT NULL
);

INSERT INTO posts (title,body,created)
    VALUES ('タイトル', 'これは、記事の本文です。', NOW());
INSERT INTO posts (title,body,created)
    VALUES ('またタイトル', 'そこに本文が続きます。', NOW());
INSERT INTO posts (title,body,created)
    VALUES ('タイトルの逆襲', 'こりゃ本当にわくわくする!うそ。', NOW());

データベースの設定

  • app/Config/database.php.default を app/Config/database.php にリネームして host, login, password, database などを修正

キャッシュ用のディレクトリへウェブサーバーが書き込みできるように

  • ウェブサーバーの実行ユーザーを ps 等で確認して、キャッシュ用のディレクトリへウェブサーバーから書き込みができるようにする
chown -R www-data app/tmp

ウェブサーバー設定

  • CakePHPをチェックアウトしたディレクトリをウェブサーバーで公開する

MVC

Model

  • posts テーブルに接続するモデルを app/Model/Post.php に記述
  • これはデフォルトで PostsController から呼び出すことができる
<?php
class Post extends AppModel {
}

Controller

  • /posts/ でアクセスできるコントローラーは app/Controller/PostsController.php に記述
<?php

class PostsController extends AppController {

    public $helpers = array('Html', 'Form');
    
    # /posts/index でアクセスできるアクションの宣言
    public function index() {
    
        # view の $posts 変数に値をセット
        $this->set('posts', 
            # Post モデルの全レコード取得
            $this->Post->find('all')
        );
    }
}

View

  • /posts/index でアクセスできるビューファイルを app/View/Posts/index.ctp に記述
  • コントローラーでセットされた posts の中身は以下の通り
Array
(
    [0] => Array
        (
            [Post] => Array
                (
                    [id] => 1
                    [title] => タイトル
                    [body] => これは、記事の本文です。
                    [created] => 2008-02-13 18:34:55
                    [modified] =>
                )
        )
    [1] => Array
        (
            [Post] => Array
                (
                    [id] => 2
                    [title] => またタイトル
                    [body] => そこに本文が続きます。
                    [created] => 2008-02-13 18:34:56
                    [modified] =>
                )
        )
    [2] => Array
        (
            [Post] => Array
                (
                    [id] => 3
                    [title] => タイトルの逆襲
                    [body] => こりゃ本当にわくわくする!うそ。
                    [created] => 2008-02-13 18:34:57
                    [modified] =>
                )
        )
)
  • テンプレートの中身は以下の通り
<h1>Blog posts</h1>
<table>
    <tr>
        <th>Id</th>
        <th>Title</th>
        <th>Created</th>
    </tr>

    <!-- ここから、$posts配列をループして、投稿記事の情報を表示 -->
    <?php foreach ($posts as $post): ?>
    <tr>
        <td><?php echo $post['Post']['id']; ?></td>
        <td>
            <!-- 
                $this->Html で Html ヘルパーの link メソッドを使用する 
                $this->Html->link("リンク文言", "リンク先データ")
            -->
            <?php echo $this->Html->link($post['Post']['title'],
array('controller' => 'posts', 'action' => 'view', $post['Post']['id'])); ?>
        </td>
        <td><?php echo $post['Post']['created']; ?></td>
    </tr>
    <?php endforeach; ?>
    <?php unset($post); ?>
</table>

個別のブログ記事画面を追加する

コントローラーにアクションを追加
  • app/Controller/PostsController.php にアクションを追加
<?php
class PostsController extends AppController {
    public $helpers = array('Html', 'Form');

    public function index() {
         $this->set('posts', $this->Post->find('all'));
    }
    
    # /posts/view でアクセスできる個別のブログ記事画面用のアクションを追加
    # $id パラメータを指定すると /posts/view/$id というURLでパラメータを渡せる
    public function view($id = null) {
        
        # これから取得するpostsのレコードのidを指定する
        $this->Post->id = $id;
        # レコードの取得とView変数へのセット
        $this->set('post', $this->Post->read());
    }
}
ビューの追加
  • app/View/Posts/view.ctp を記述
<h1><?php echo h($post['Post']['title']); ?></h1>

<p><small>Created: <?php echo $post['Post']['created']; ?></small></p>

<p><?php echo h($post['Post']['body']); ?></p>

記事を書き込む画面を追加する

アクションの追加
<?php
class PostsController extends AppController {
    
    # Session ヘルパーと Session コンポーネントの使用
    public $helpers = array('Html', 'Form', 'Session');
    public $components = array('Session');

    public function index() {
        $this->set('posts', $this->Post->find('all'));
    }

    public function view($id) {
        $this->Post->id = $id;
        $this->set('post', $this->Post->read());

    }
    
    # 記事を書き込む画面のアクション追加
    public function add() {
    
        # POSTメソッドでアクセスされた時の処理
        if ($this->request->is('post')) {
            if (
                # POSTされたデータをpostsテーブルにインサート
                $this->Post->save(
                    # すべてのCakePHPのリクエストは CakeRequest オブジェクトに格納されており、$this->request でアクセスできる
                    # ユーザがフォームを使ってデータをPOSTした場合、その情報は、 $this->request->data の中に入ってくる
                    $this->request->data
                )
            ) {
                # Session コンポーネントの setFlash でリダイレクト後のページで表示するメッセージを引き継ぐ
                $this->Session->setFlash('Your post has been saved.');
                # 一覧へリダイレクト
                $this->redirect(array('action' => 'index'));
            } else {
                $this->Session->setFlash('Unable to add your post.');
            }
        }
    }
}
ビューの追加
  • app/View/Posts/add.ctp に記述
<h1>Add Post</h1>
<?php
# Form ヘルパーでフォームの作成
echo $this->Form->create('Post');
echo $this->Form->input('title');
echo $this->Form->input('body', array('rows' => '3'));
echo $this->Form->end('Save Post'); # フォームの終了
?>
  • app/View/Posts/index.ctp に導線を追加
<?php echo $this->Html->link('Add Post', array('controller' => 'posts', 'action' => 'add')); ?>
バリデーションルールの追加
  • app/Model/Post.php に Form ヘルパーと連携してバリデーションを実行するバリデーションルールの設定を追加する
<?php
class Post extends AppModel {
    public $validate = array(
        'title' => array(
            'rule' => 'notEmpty'
        ),
        'body' => array(
            'rule' => 'notEmpty'
        )
    );
}

記事編集画面の追加

コントローラ
  • PostsControllerに以下のアクションを追加
    public function edit($id = null) {
        $this->Post->id = $id;
        if ($this->request->is('get')) {
            $this->request->data = $this->Post->read();
        } else {
            if ($this->Post->save($this->request->data)) {
                $this->Session->setFlash('Your post has been updated.');
                $this->redirect(array('action' => 'index'));
            } else {
                $this->Session->setFlash('Unable to update your post.');
            }
        }
    }
ビューの追加
  • app/View/Posts/edit.ctp を記述
<h1>Edit Post</h1>
<?php
    echo $this->Form->create('Post', array('action' => 'edit'));
    echo $this->Form->input('title');
    echo $this->Form->input('body', array('rows' => '3'));
    echo $this->Form->input('id', array('type' => 'hidden'));
    echo $this->Form->end('Save Post');
?>
編集画面への導線追加
  • 一覧画面の個別の記事から編集画面への導線を追加する
<h1>Blog posts</h1>
<p><?php echo $this->Html->link("Add Post", array('action' => 'add')); ?></p>
<table>
    <tr>
        <th>Id</th>
        <th>Title</th>
        <!-- 追加箇所その1 -->
        <th>Action</th>
        <!-- /追加箇所その1 -->
        <th>Created</th>
    </tr>

<!-- $post配列をループして、投稿記事の情報を表示 -->

<?php foreach ($posts as $post): ?>
    <tr>
        <td><?php echo $post['Post']['id']; ?></td>
        <td>
            <?php echo $this->Html->link($post['Post']['title'], array('action' => 'view', $post['Post']['id'])); ?>
        </td>
        <!-- 追加箇所その2 -->
        <td>
            <?php echo $this->Html->link('Edit', array('action' => 'edit', $post['Post']['id'])); ?>
        </td>
        <!-- /追加箇所その2 -->
        <td>
            <?php echo $post['Post']['created']; ?>
        </td>
    </tr>
<?php endforeach; ?>

</table>

削除画面の追加

アクションの追加
    public function delete($id) {
        if ($this->request->is('get')) {
            throw new MethodNotAllowedException();
        }
        if ($this->Post->delete($id)) {
            $this->Session->setFlash('The post with id: ' . $id . ' has been deleted.');
            $this->redirect(array('action' => 'index'));
        }
    }
導線の追加
  • 一覧画面のeditの隣にdeleteへの導線を追加
            <?php echo $this->Form->postLink(
                'Delete',
                array('action' => 'delete', $post['Post']['id']),
                array('confirm' => 'Are you sure?'));
            ?>

ルーティング設定

  • / へのアクセス時に /posts/index を表示するようにする
  • ルーティング設定は app/Config/routes.php にある
  • これのデフォルトページへのルーティング設定をコメントアウトして、/posts/index への設定を追加する
## 元の設定
# Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
## 追加分設定
Router::connect('/', array('controller' => 'posts', 'action' => 'index'));

さいごに