「CakePHP1.2ガイドブック」を実際に作りながらレビュー

cakephp_1_2_guidebook.jpg

CakePHP初心者さんようこそ!

CakePHPとは…ってもうここに来る人はみんな知ってますよね。

さて、PHPがどんなものか分かったら、CakePHPのような優秀なフレームワークを使ってガシガシアプリを作っていくのがプログラマーとして何より早道かもしれません。

逆に「プログラミングは初めてです」という人には、PHPは楽しい言語なのでお勧めですよ。ただ、しっかり基礎を勉強してきましょう。 基礎が出来たらCakePHPで楽しくアプリ作りを楽しんでください。

というわけで私事ですが私も「CakePHP」を使ってPHPアプリを制作することになったので「CakePHP1.2ガイドブック」を購入してきました。 帯にも「CakePHP1.2公認ガイドブック」と書かれているので期待が持てます。 うーん、やっぱり本はいい。

でも、ただ読んで作ってそのままってのも勿体ないので、作りながら引っかかったところを書いていきたいと思います。 ちなみに、本は2009年7月10日に発行されたばかりなので初版本です。

ガイドブックの王道を行く序盤

この本の特徴として、序盤では実際に手を動かしてシステムを作りながら感触を知ってもらう構成になっております。 具体的な範囲としては、XAMPPの設定からbakeを使ったscaffold(足場組み)まで。 CakePHPを知らない人には「何?その呪文?」って思われそうですが。。

もっと分かりやすく言うと、WEBサーバーとデータベースサーバーの設定から、CakePHP専用のウィザードを使ってとりあえず見れるものを作れるところまで、です。

初心者にはこのあたりがものすごく安心できる要素かもしれませんね。 「おおー、なんかシステムができてきた!」ってのを実感しながらCakePHPを学んでいってる実感が沸きますから。 自転車の練習と同じと思います。 とにかく慣れよ!です。

ノートパソコンさえあればどこででも勉強できる環境がステキ

最初の環境インストール作業以外は、基本的にローカル環境のみで作業が行えます。 XAMPPという便利なオールインワンパッケージとCakePHPをインストールできたらカフェなどに行っても良しです。 後半にはちゃんと公開されたサーバーに配置する方法が学べますのでご安心を。 個人的に私が助かっているところはここですかね。 どこに行ってもできるというのは重要ですよ。

知り合いに作ってるところを見せて意見を聞いたり、分からないところを実際に動かしながら教えてもらったりできますからね。

引っかかりそうな箇所を厳し目に指摘。

ガイドブックで学習する人は、つまづいたらここに来てみてください。 同じところでつまづいてるかもしれませんから。笑

4-3-12 完成したWEBアプリケーションを確認する

最初からかなり順調に飛ばしていたのですが(本を読み飛ばしていたのではないですよ!)、P45「4-3-12 完成したWEBアプリケーションを確認する」、この項目で引っかかってしまいました。

何回Model, Controller, Viewをbakeしても関連テーブル情報が出てこないのです。

具体的には、customerの一人目を表示したページに「Related Order Records」という表示が出るはずなのですが、、出ていない。

検索してみると、「View」をbakeで作り直せばいいよ、というアドバイスがあったのですが、こちらではそれもうまくいきません。

悩んでいると、「あ…!」一つ重要なことに気づきました。 Dreamweaverです。

そう、Dreamweaverのサイト管理機能でCakePHPのインストールディレクトリを表示させたままbakeを実行しまくっていたのです。

bakeで構築しなおすと当然既存のファイルは上書きされるはずなのですが、Dreamweaverで表示されていたことによってファイルハンドルがガッシと掴まれて上書きがされていなかったのです。 この辺り、bakeが親切なら「上書きに失敗しました」的なメッセージが出ても良いのでは、と思うのですが、さすがにそこまでは気を使ってくれないようです。

Dreamweaverを終了させてbakeしなおすと、アッサリとできてしまいました。 いままでDreamweaverの中だけで作業をしていた人は要注意項目ですね。 とりあえず、解決です。 ホッ。。

4-4 default.ctp

P51の記事の中で書き間違い発見。 本には以下の記述がありますが

このすべてのページの土台となるデザインは、
cake/libs/view/templates/layouts/default.ctp
の中に書き込まれています。

上記ディレクトリにはありませんでした。 正確には

cake/libs/view/layouts/default.ctp

でした。 しかし、ここのテンプレートをコピーして/appのほうに移してh1タグの部分を日本語のタイトルにしたら文字化けしましたよ…? コードがおかしいのでしょうか…

cakeError

P76にある「cakeError」の項目が若干分かりにくかったです。 以下のようにしてControllerクラス上の共通のエラー処理で利用するメソッドですが

$this->cakeError(メソッド名, 連想配列);

本では「app/AppError.php」を作成すると拡張できるとあって、その下にcakeErrorを使ったと思われるサンプルview画面が載ってましたが、具体的な書き方は載ってませんでした。この辺り、何かサンプルコードがあると分かりやすいんじゃないですかね?

6-3-5 Viewの作成

サンプルアプリケーションの制作は実際動いている画面が見られるのでほんとに楽しい項目なのですが、P92のViewのXHTML作成でlogin.ctpをコーディングする箇所で若干間違いがありました。

<form action="login_cmp" method="post">
メールアドレス
<input type="text" name="email">
<br />
パスワード
<input type="password" name="password">
<br />
<input type="submit" value="ログイン">

これはXHTMLなので以下が正解ですね。 inputタグはインライン要素なので終了タグを付加しないといけません。

<form action="login_cmp" method="post">
メールアドレス
<input type="text" name="email" />
<br />
パスワード
<input type="password" name="password" />
<br />
<input type="submit" value="ログイン" />

6-3-6 動作確認

ありゃ?文字化けだ

ログインフォームからメールアドレスとパスワードを入力すると、/app/controllers/users_controller.phpの以下のメソッドに処理が移って、「ログイン成功?」と表示されるはずなのですが

function login_cmp()
{
$this->flash("ログイン成功?", "/bookmarks/");
}

文字化けしてしまいました… なんでだろう?

flashメソッドを呼んだ際に表示されるページで文字化けが起こっています。

この文字列はusers_controller.phpに記述されているものなので、確認のために文字コードを調べてみると「Shift_JIS」になっちゃってました。。

うーん、bakeでControllerを作ってしまうと標準で「Shift_JIS」になってしまうようです。 あとでテキストエディターなどで「UTF-8N」に変換してあげるとちゃんと文字化けしないで表示されるようになりました。 良かった良かった。

6-3-8 セッションを利用した認証機能の実装例

いやー、ここの認証機能の簡単さもすばらしいですね。 自力で書いていたのがアホらしく感じるほど。

ただ、ここも本どおりにいかないところがありました。 ログインが成功した後のP99の画面ですが、これは/app/config/core.phpのデバッグの値を0にしておかないと画面遷移しないですね。

Configure::write('debug', 2); (ここの2を0にします)

ところで画面下のクエリー情報はデバッグの値が0だと表示されないので、どうやっているのか謎です。。

…と思ったら、$this->flash()で表示された画面は、タイトル部分をクリックすると指定のURLに遷移するのですね。。 ようやく分かりました。

6-3-9 ログイン中のユーザー情報を元にした処理

ここもViewの文字化けで悩みました。 P100のapp/views/bookmarks/index.ctpですが、最初に文字コードを変更しようとTeraPadを使ってUTF-8Nに変換したのですが、何度やってもShift_JISのまま。

埒があかないので、コーディングだけ先にやって表示だけさせてみました。

すると、案の定文字化け。。

ただ、index.ctpの内容がXHTMLベースのシンプルなものになったので、再度TeraPadで開いてUTF-8Nに変換。 すると、文字化けが直りました。

Viewはいずれ変更するのでこのような問題はあまり起こらないのでしょうが、本を見ながら学んでいる人にはけっこう精神的にまいる所かもしれません。

7-2-4 データを取得する

リスト7-7 find(‘all’)の使用例3(関数の実行例)

P114の「リスト7-7 find(‘all’)の使用例3(関数の実行例)」で見慣れない記述が出てきたので戸惑いました。 Modelで条件を指定してfind()で取り出ししているところです。

$data = $this->Bookmark->find('all',$param);
$this->set("data",$data);
//集計結果をメッセージ表示領域へ格納
$this->Session->setFlash(var_export($data[0][0],true);

2行目までは分かるのですが、最後の行がなんなのか分かりません。setFlash()って?

調べてみると$this->Session->setFlash()は画面に一瞬表示させるメッセージをセットする命令であるということです。

setFlash()

setFlash($message, $layout = 'default', $params = array(), $key = 'flash')

ビューで出力するために使用するセッション変数をセットします。$layout で /app/views/layouts にあるものを指定することで、メッセージを表示する時にどのレイアウトを使用するかをコントロールできます。$layout を「default」のままにしておいた場合、メッセージは次のコードでラップされます。

<div id="flashMessage" class="message"> [message] </div>

$params では、表示されるレイアウトに追加のビュー変数を渡すことができます。$key には Message 配列の $messages インデックスをセットします。デフォルトは「flash」です。
パラメータでは、レンダリングされる div タグに影響を与えることができます。たとえば、 $params 配列に「class」をキーとして値を与えると、 $session->flash() で出力したレイアウトの div タグの中に class 属性を付与します。

7-2-7 データバリデーション

ここでは、例として名前(name)とメールアドレス(mail)とパスワード(password)の入力の正当性をチェック(validate)するモデルがコード例で出ています。

その中でエラーメッセージを設定している箇所があるのですが、ControllerやViewではどうするのかが書かれていませんでした。 ここはModelを説明しているところなので詳しく書いても混乱すると考えたのでしょうけど、「ControllerやViewについては後で説明するので省略します」等の安心感を与える記述があっても良かったのでは、と思いました。

あと、誤字修正。 P142の「validates()」を呼び出しているところ。

$ths->モデル名->validates()

ここは

$this->モデル名->validates()

ですね。

7-3-3 ブックマーク登録機能の作成

ここは本に従ってゴリゴリと作っていくところですが、validates()の箇所で間違いを発見。

P149の下部のコード例でブックマーク情報を検証する箇所がありますが

//モデルにデータをセットする
$this->Bookmark->set($data);
//入力検査に失敗した場合は再度、入力画面へ
if ( !$this->Bookmark->validates($data) ) {
...

ここはvalidates()には引数は必要ないはずなので

//モデルにデータをセットする
$this->Bookmark->set($data);
//入力検査に失敗した場合は再度、入力画面へ
if ( !$this->Bookmark->validates() ) {
...

これが正しいですね。P142のコード例でも引数なしで記述してありますから。

あれ?Viewで警告メッセージが…

P150でView用のapp/views/bookmarks/add.ctpを作成したのですが、フォームを表示させると表示にエラーが出てしまいました。どうやらフォームに$urlの内容を表示させる部分で「そんな変数ないよ」というエラーが出ているようです。 見てみると以下のコードが該当する箇所です。

<input type="text" name="url" size="40" value="<?php echo h($url); ?>" />

ここの$url変数はController(app/contollers/bookmarks_controller.php)ではvalidates()で失敗した後に$this->set()で設定してあるのですが、最初にフォームを表示させた時点は設定されていないことになります。 なのでフォームでは値が設定されていることを確認した上で表示させないといけないですね。 というわけで上記のコードを修正してみました。

<input type="text" name="url" size="40" value="<?php if (isset($url)) echo h($url); ?>" />

これで警告が出なくなりました。CakePHP的に合ってるのかなこれ?笑 ま、先が分からないのでこのまま進みましょう。

7-3-4 検索機能の作成

$this->User->find(‘list’)でエラー

これは実際動かしてみるまで分からなかったのですが、P151のapp/controllers/bookmarks_controller.php でのsearch()メソッドの中で、ユーザーのリストを取得する部分。

//ユーザーのリストを取得
$user_list = $this->User->find('list');

ここでエラーが出てました。 scaffoldで組まれた見本のコードを見ると、どうやらここは

//ユーザーのリストを取得
$user_list = $this->Bookmark->User->find('list');

とするのが正解のようです。 これで無事エラーがなくなりました。 しかし、ここは分からない人には分からない箇所なので、致命的な間違いかもしれません。 技術書ってこういうところがあるから書くのが難しいですよね。 Amazonのブックレビューでもよく指摘されたりしますし。。

またしつこくXHTMLの指摘

P153の検索フォームでのコーディングでXHTML式になっていない箇所を2箇所発見。

<td><select name="user_id[]" multiple>
<?php foreach ($user_list as $key => $val): ?>
<option value="<?php echo $key;?>" <?php if (in_array($key, $user_id)) echo "selected";?>><?php echo h($val);?></option>
<?php endforeach; ?>
</select></td>

以下のように属性がちゃんと「(属性名)=(属性値)」になるようにします。

<td><select name="user_id[]" multiple="multiple">
<?php foreach ($user_list as $key => $val): ?>
<option value="<?php echo $key;?>" <?php if (in_array($key, $user_id)) echo 'selected="selected"';?>><?php echo h($val);?></option>
<?php endforeach; ?>
</select></td>

7-4 まとめ

column DBテーブルを使わない場合にも使えますか?

P157で誤字発見。「$useTalbe=falseを設定して」のところは「$useTableを設定して」の間違いですね。

8-2-3 Form

誤字が多いFormヘルパーの表…

なんだかここに来て急に誤字が目立ってきました。

P171の「表8-2 Formヘルパーの主な機能概要」の所ですが、まず「input」の項目。「iinputタグを出力する」は「inputタグを出力する」の間違い。

次に「textarea」の項目。「ファイルアップロード欄を出力する」とありますが、これは「テキストエリア欄を出力する」の間違い。説明する行が間違ってます…

次の行の「fle」の項目。これは「file」ですね。で、説明が「テーブルセルtdを生成する」って…、これは「ファイルアップロード欄を出力する」ですね。P163の表をコピペしたのがバレバレですね…

ヘルパーの利用

ここでは、ページの表示を行うための便利なオブジェクトの紹介とそのコーディング方法について記述されています。

この部分については実際の作業現場にて思うところがあるのでちょっと語りますね。

ヘルパーはGUIデザインなどを行うWebデザイナーやHTMLやCSSをコーディングするコーダーと、プログラマーとの連携作業において、若干Webデザイナーに面倒を強いる部分があるのではないかと考えています。

実際に表示させるまで想像できないページの見栄え

HTMLコーディングを行うWebデザイナーの中には当然プログラマーじゃない人もいるわけで、プログラマーと平行作業を行う場合、アンケート入力フォームを例に挙げるとコーディングなどは作業効率上Webデザイナー側が行う場合がほとんどではないかと思います。

この場合に「こういうフォームデザインをやりたい」とWebデザイナーが思ったときにヘルパーを利用するルールになっているとHTMLコードではなくPHPコードを埋め込まないといけないので、実行時に生成されるHTMLコードをWebデザイナーが事前に想定してデザインしにくいというストレスが発生します。

ヘルパーにはオプションを指定する部分もあって、そこでclass名などを指定できるようですが、それはすでにPHPの領域であって、Webデザイナーがプログラマーの作業に関わらざるを得ない状況です。

一人で全部開発をやってしまう場合は全体を把握できているので問題ないかもしれませんが、Webデザイナーやプログラマー双方のコンテンツの変更というのは実際の開発中に思った以上に発生するものですから、この役割分担できる部分というのは極力粗結合な状態を保つのが良いです。

Smartyのススメ

Smartyこの部分について良い解決法としては、やはりSmartyの活用が適切なのではないかと個人的に考えています。 Smartyであれば基本的にHTMLコードやCSSなどはWebデザイナーの領分として書き進めることができるので、連携という意味では「デザイナー向けのSmarty構文のみを知っていれば良い」という粗結合の関係にすることができます。

Smartyを利用したプロジェクトでは私がコントローラー(C)を書きつつ、横でプログラムが分からないコーダーの人が私に関係なくコーディング(V)を進めて、結合テストがスムーズにいくことが少なくありません。

まだ本格的に活用していないので「いやいや、プログラマーとWebデザイナーでもCakePHPだけでうまく連携できるよ」という方もいらっしゃるかもしれません。 その場合はぜひノウハウを共有させていただければと思います。

ちなみにこの本では後半にちゃんとSmartyと連携するための方法が書かれてあります。 ほんと至れりつくせりで欲しい機能がちゃんと考慮されていますね。

その解説導入部分でもこのようなことが書かれています。

特にビューテンプレートに関しては、Webデザイナーが更新を行うケースが多いので、テンプレートの書式を変更するのが難しい場合があります。

10-1 コンポーネントを作る

10-1-4 フックメソッドの実装

誤字です。P238の「フレークワーク」は「フレームワーク」が正解。

あと、ここの表10-1にコンポーネントのフックメソッド5種(initialize(),startup(),beforeRender(),shutdown(),beforeRedirect())が記載されていて、表タイトルが「Viewクラス-フレームワークで設定される変数」とありますが、これは明らかに異なるタイトルでしょう。笑 P242の表タイトルが一部コピペされています。 正式には「フックメソッドの種類と呼び出しタイミング」のようなタイトルにしないとですね。

ついでに、これらのフックメソッドの使い分けのコツみたいなものがあるとフックメソッドの利用シーンが具体的にイメージできて良かったのではないかと思います。

10-2 ヘルパーを作る

10-2-1 クラス

ここではSimpleHelperクラスがAppHelperクラスを継承し、さらにAppHelperクラスがHelperクラスを継承しているクラス図が描かれています。 継承が矢印で記述されているのですが、UML的に正確に描かれていません。 これは初心者にも分かりやすくしたためでしょうかね。 誤解を与えないためにもUML式に描いておいて問題ないと思いますが。

10-3 ビヘイビアを作る

10-3-1 クラス

ここでも「10-2-1 クラス」で描いてあったクラス図の描き方でSimpleBehaviorの継承先が示してあります。やっぱりUMLで良さそう。

10-3-4 フックメソッドの実装

CRUD処理って?

P249にさりげなく登場している「CRUD処理(クラッド)」という用語ですが、これは一般的なデータ処理に必要な4つの機能である、作成(Create)、読み出し(Read)、更新(Update)、削除(Delete)をまとめた言葉です。 後半に丁寧な説明が出てきますが、ここで説明したほうが良かったのでは。

10-5 まとめ

ヘルパー、コンポーネント、ビヘイビアを学んだまとめという項目ですが、なんとユーザー認証をAuthComponentを利用したやり方で新たに書き直すという作業が行われます。 もはや「まとめ」ではなく新機能です。笑

この「まとめ」の項目は制作者は必ず把握しておくべき箇所です。 以下理由。

AuthComponentを利用すべき3つの理由

  • 利用する各コントローラーに同一のログインの仕組みを組み込める
  • ログインフォーム表示後にリダイレクトして目的のページを再度表示させるloginRedirect()メソッドが使える
  • パスワードをConfigurationのSecurity.saltを使ってハッシュ化させる仕組みが使える

つづく。。

このページをシェアする

2009-09-13