CakePHPハンズオン@tokyoに参加してます

CIMG1477

本日、ウノウにてCakePHPハンズオン@tokyoが開催されております。

最近、「ちょっとした軽いのをぱぱっと作るにはやっぱりPHP便利だよなー」とPHP再評価フェーズに入っているので参加しています(現在進行形)。

以前は自作の俺俺フレームワークでせこせこと組んでいたんですが、今からまたPHPやるならちゃんとしたフレームワーク使うべきだよなと。symfonyが合うような場面だと、今の自分としてはむしろPHPじゃなくてPerlを使いたいので、それならCakePHPが合うんじゃないかなと期待して参加しました。

会場は、ノートPC持参で集まって、公式の CakePHPブログチュートリアル をこなしながらid:yandodさんのお話を聞くという流れ。

リアルタイムのメモなので、粗いのと、個人的な感想を交えているので読みにくいかも知れないけど、そのへんは勘弁。もう懇親会に行ので内容も全く確認できてないけど上げちゃう。

■DB定義

DBスキーマのファイルはapp/config/sql/に置いたけど、それがデファクトということでもないらしい。
SESSIONとかACL管理など、Cakeが提供する機能のためのテーブルが定義されているのであって、アプリケーションで使用するスキーマを置く場所として用意されているわけではないそうな。基本的には「好きなところに置け」ってスタンスらしい。

■Scaffold

公式チュートリアルから少し離れた内容。

app/controllers/posts_controller.php

<?php
class PostsController extends AppController {
    //var $name = 'Posts';
    var $scaffold;
}

これでデフォルトのScaffoldが動く。
1.2からModelを作らなくてもScaffoldが動くようになった。
$nameの定義はPHP4対策なので5なら不要。

■通常の実装

<?php
class PostsController extends AppController {
    public function index() {
        $this->set('posts', $this->Post->find('all'));
    }
}

Controllerをこうしておいて、Viewを作らずにブラウザから見るとエラーを出してくれる。
こういう、エラーメッセージでユーザーを導くやり方は面白いよね。
ちゃんと検証してないけど、setした時点でHTMLエスケープしてくれるっぽい。(08/24訂正)setしただけではエスケープされてませんでした。ヘルパーがエスケープ処理をしてくれてました。
$this->getは無かった。Viewに渡した値をControllerでもう一度取るのはどうするのかな。

発行したSQLも合わせて表示してくれるんだけど、

SELECT `Post`.`id`, `Post`.`title`, `Post`.`body`, `Post`.`created`, `Post`.`modified` FROM `posts` AS `Post` WHERE 1 = 1 

「WHERE 1=1」はキモい。

POST値はControllerの$this->dataで拾える(GET値は入らないみたい(?))。
Controllerに渡ってきた諸々の情報は、$this->paramsから取れるのかな。

フォームの要素はヘルパー使って出力するとエラーメッセージもよしなにやってくれるから、手書きよりヘルパー使った方がいい。
エラー時に <input class="form-error" 〜/> てな具合にエラーのクラスも吐いてくれるのは嬉しい。

■サンプルに不具合が見つかった件

Controllerで、

public function edit ($id = null) {
    $this->Post->id = $id;
    if (empty($this->data)) {
        $this->data = $this->Post->read();
    } else {
        if ($this->Post->save($this->data['Post'])) {
            $this->flash('Your post has been updated.', '/posts');
        }
    }
    $this->render('add');
}

てな具合にeditを実装した場合、editフォームでエラーを発生させて、その後POSTするとIDが取れなくなって、updateじゃなくてinsertが走ってしまう。
時間がないので、この場はスルー。解決策はid:yandodさんがまた出してくれるはず。
IDもPOSTするのか、フォームのactionを書き換えるのか。
フォームのactionがURLを引き継ぐようなやり方が綺麗な気がするけど、そういう機能はあるのかな。

■ルーティング

/app/config/routes.php で制御する。

■コードシュガー

e(h($hoge)) → echo htmlspecialchars($hoge, ENT_QUOTES)

実は最近までENT_QUOTESされてなかったらしい…

a('one', 'two', 'three') → array('one', 'two', 'three')
aa('hoge', 'foo', 'bar', 'oge') → array('hoge' => 'foo', 'bar' => 'oge')

後者はよろしくないんじゃないか?

■ControllerからModelを呼ぶ

var $users = array('Model1', 'Model2', ...);

■Modelのテーブル変更

class User extends AppModel {
    var $useTable = 'user_account';  // 好きなテーブル名を使う
    var $primaryKey = 'login_id';    // Pkeyも好きなカラム名に
}