Top > CakeShop > イテレーション > 2-A2 商品を注文する

RIGHT:&tag(CakeShop);
#contentsx

* イテレーション [#r894c9c4]
* 2-A2 商品を注文する [#r894c9c4]
ユースケースの中の注文する流れを作ることにする。
少し、ボリュームが多いように感じるが、イレギュラー処理は後で手直しするとして正常系の注文までができるようにする。

|~イテレーション番号|2|
|~対象ユースケース|A-商品を注文する|
|~期間|2007.2.5〜2007.2.11|
|~メンバー|opaken|
|~目標|商品をカートに入れて注文するところまで作る。|

** テーブル構造のエクスポート [#idfd952d]
-phpMyAdminに手動で作ったテーブルの構造をSQLとしてエクスポートしておく。
-エクスポートのSQL オプションで構造にチェック
--DROP TABLE / DROP VIEWを追加>>チェック
--IF NOT EXISTSを追加>>チェック
--「AUTO_INCREMENT値を追加する>>チェックしない
--逆クオートでテーブルやフィールドを囲む>>チェック
-データには、チェックせずに「実行する」ボタンをクリックするとCREATE TABLEのSQLが表示する

** 商品詳細ページ設計 [#x036a765]
-表示するべき項目を整理する。
-画面仕様を簡単にまとめる。
-該当商品が見つからなかった場合は、「商品が見つかりませんでした」と表示する。
-[[CakeShop/画面設計/商品詳細(items)]]
に整理した。
-画面仕様としては、アクションと表示項目、エラーメッセージをまとめておくこと。

** ページテンプレートの修整 [#s7a37cef]
-メニューのリンクを修正して、作っているページへのリンクを付けておく。
 <?php echo $html->link('商品詳細', '/items/index/1')?>

** アプリケーションの共通設定 [#y12dbe57]
-共通設定は、shop/config/app.ini.php ファイルにグローバル定数として記述するようにする。
 <?php
   define('MAIL_SMTP', 'mail.example.com');
 ?>
kitchen/config/app.ini.phpにも同じ内容をとりあえず用意する。
-共通設定をインクルードするように shop/config/bootstrap.php に追加する。
 // アプリケーションの共通設定
kitchen/config/bootstrap.phpにも同じ内容をとりあえず用意する。
-ビューを修正して値が取れるか確認。
 <?php echo constant('MAIL_SMTP') ?>

** ModelなしのController [#od9b6e9f]
$usesにnullか空の配列「array()」を指定するだけでOKだそうです。
 class MyController extends AppController
 {
     // var $uses = null; works too
     var $uses = array();
 
     function index()
     {
     }
 }

** Ajaxを使ったCRUDのサンプル [#y79bf24b]
-サンプルのソースを下記ページからダウンロード
[[CakePHP :: A Rapid Development Framework :: Posts:http://infor96.com/cake/posts/]]
-動かして見たが、エラーになったので、
views/elements/ajax_post_list.thtmlを修正した。
どうも、ajaxのhelperで、linkToRemoteメソッドが、linkメソッドに移行したようだ。メソッドのパラメータ仕様も変更しているみたい。URLがarrayのオプションで指定するのではなく、第2引数で指定するようになっているようだ。
 <td><?php echo $ajax->link('View', "/posts/view/{$post['id']}" ,array('fallback'=>'#view', 'update'=>"post_content", 'complete'=>"new Effect.Appear('post_content');")) ?>
 | <?php echo $ajax->link('Edit', "/posts/edit/{$post['id']}", array('fallback'=>'#edit', 'update'=>"edit_post", 'complete'=>"new Effect.Appear('edit_post');")) ?>
 | <?php echo $ajax->link('Delete', "/posts/delete/{$post['id']}", array('fallback'=>'#list', 'update'=>"post_table", 'complete'=>"stripe();initDrag();")) ?>  
 </td>

** CakePHPのバージョンアップ [#d488833a]
-CakePHP1.1.13.4450がリリースされている。
1.1.13.4450はバグフィックスリリースで多くの変更・修正が行われており、CakePHP Sessonコンポーネントに任意のコードが実行できる脆弱性も修正されている。
[[CakePHP1.1.13.4450&1.2.0.4451alphaリリース | Shin x blog:http://www.1x1.jp/blog/2007/02/cakephp11134450_1204451alpha.html]]
-どのファイルがバグフィックスで変更されたか分からない。
--どうやって、適用するか検討が必要。

** 共通で使うコンポーネント [#if3fcd7e]
-AppController側で設定していると、全てのコントローラで使えるようになる。個別で使うコンポーネントだけを各コントローラで指定すれば、両方とも使える。
[[CakePHP controller共通のモデル、コンポーネント、ヘルパーを設定する | Shin x blog:http://www.1x1.jp/blog/2006/09/cakephp_common_models_components_helpers.html]]
 <?php
 class AppController extends Controller {
   var $components = array('RequestHandler');
 }
 ?>

** バリデーションの強化 [#c1437dac]
-CakePHP 1.2のバリデーションを1.1で使うようにする。下記のページを参考にした。
[[hetimaの日記 - CakePHP 1.1系に1.2系のバリデーションを組み込む:http://d.hatena.ne.jp/hetima/20070202/1170344802]]
cake/libs/validators.php
↓
cake/libs/validators_1.1.php
に名前変更し、
[[ここ>https://trac.cakephp.org/browser/branches/1.2.x.x/cake/libs/validation.php?format=raw]]からダウンロードした、CakePHP 1.2用のvalidation.phpを
cake/libs/validators.php
に名前を変更してコピーする。
-下記のページもバリデーションの事が書いているので見ておく。
[[onkn101の備忘録 - CakePHPのvalidation:http://d.hatena.ne.jp/onkn101/20070102/1167699730]]

** ログの出力ができない [#v5ea2ce1]
-$this->log('hoge')でログを出力しようとするとエラーになる。
原因は、
[[Webプログラミングに関するメモ: CakePHPの$this->log()、php4.4.4でエラー:http://asaton.seesaa.net/article/32237074.html]]
に書かれていた。
取り急ぎ、file.phpのcreate()メソッドを修正して対応。
$this->getName()
↓
$this->name
※2箇所
-kitchen/tmp/logs/error.logファイルにログが書き込まれるようになった。

** CakePHPのログをLog4phpに切り替える [#bb08efcd]
-Log4JのPHP版を使うようにする。
[[PHP/CakePHP/CakePHPのログをLog4phpに切り替える]]

** htmlタグのカスタマイズ [#b1c732bc]
-tags.ini.phpで修正できるそうなのだが、入っていなかった。
https://trac.cakephp.org/browser/branches/1.1.x.x/cake/config/tags.ini.php?rev=3261
からダウンロードして、app/configの下に入れると反映されるみたい。
-ラジオボタンにラベルを付ける。
tags.ini.phpを修正
 radio = "<input type="radio" name="data[%s][%s]" id="%s" %s />%s"
 ↓
 radio = "<input type="radio" name="data[%s][%s]" id="%s" %s /><label for="%s">%s</label>"
cake/lib/view/helper/html.phpのradioメソッドを修正
 $out[] = sprintf($this->tags['radio'], $this->model, $this->field, $individualTagName, $parsedOptions, $optTitle);
 ↓
 $out[] = sprintf($this->tags['radio'], $this->model, $this->field, $individualTagName, $parsedOptions, $individualTagName, $optTitle);

** 区分値を表示するためのヘルパークラスを自作 [#eb9c32b1]
[[PHP/CakePHP/CakePHPで区分値の表示を簡単にするためのヘルパークラス SectionHelper]]
テーブル定義の備考欄で区分値に関しては、arrayの連想配列でそのままコピペできるように、'code1' => 'name1', 'code1' => 'name1' の形式で記述するように! 

** スタイルシートが無くなっている [#bd337fa2]
-アクセスのログを見ていると、1回しかアクセスしていないのに2回アクションが動いていて、2回目が失敗している。
-調べてみると、ページ内でcssをインクルードしているファイルが無いため発生していた。
-cake.forms.cssが無くなっているようなので、下記からダウンロードした。
https://trac.cakephp.org/browser/trunk/cake/app/webroot/css/cake.forms.css?rev=1639
-どうも、全てのアクセスをCakePHP側でチェックしているので、このような動きになっている。画像やcssのアクセスはCakePHPを通さずに行うようにしたほうが良いのでは?

** 商品詳細ページ実装 [#n0bcb2ad]
-サイズオプションはプルダウンで選択するので、下記を参考にする。
[[大盛り弁当 A large serving of lunch &#187; CakePHPでselect要素を使う:http://www.usamimi.info/~oomori/blog/cakephp-select/]]
-値が表示できない時に迷ったら、$thisの中身を見ること!
ビューで$thisの中身を表示する場合
 <?php echo pr($this); ?>
ログに出力する場合
 $this->log(print_r($this, true), LOG_DEBUG);
※print_rの2つめの引数をtrueにすると画面に表示せずに文字列で返ってくる

** decorateで作ったController [#de12579c]
-一覧からAddで追加した時に、入力画面の下になぜか一覧までもが表示されている。
XXX_controller.phpのindex()メソッドを修正
 case LABEL_ADD: //goto add page
   $this->data = null;
   $this->setAction('add');
   break;
   ↓
   exit;
ちゃんとexitしてメソッドを抜けないと2回renderしてしまうので

** 共通のコントローラーとモデルクラス [#a41f0182]
-通常は、app/app_model.php と app/app_controller.php に共通処理を記述するが、今回のCakeShopの場合は、アプリケーションフォルダが、shop と kitchen の2つになっている。
-2つのフォルダに同じファイルを置くのは冗長なので、vendorsフォルダに共通で使う専用フォルダを用意することにした。
-/vendors/cakecommons というフォルダを用意する。
その中に commons_controller.php と commons_model.phpを作る。
-アプリケーションフォルダ側のものは、vendorsフォルダのモデルとコントローラをインクルードするようにしておく。
app_controller.php
 <?php
 vendor('cakecommons/commons_controller');
 class AppController extends CommonsController {
 }
 ?>
app_model.php
 <?php
 vendor('cakecommons/commons_model');
 class AppModel extends CommonsModel{
 }
 ?>
-これで、モデルとコントローラの共通処理を1箇所にまとめることができる。

** ユーティリティ関数 [#l770e086]
-共通で使いたいユーティリティ関数をどこに置くか?
-先ほどの、vendors/cakecommons フォルダに commons.php として作ります。
-そして、app/config/bootstrap.php で インクルードするようにしておきます。
 // CakeCommonsの使用
 vendor('cakecommons/commons');
-ユーティリティ関数では、主に次のものを用意しておきます。
--エラーハンドラー(コールバック)
phpのエラー発生時にログ出力するようにした。
--デバッグトレースを画面やログに出力するための関数。

** CakePHPのモデルをエンティティとして扱う [#k121da42]
-DBから取得した値をビューで操作する時に連想配列として扱うのではなく、モデルクラスのオブジェクトとして扱いたい。
[[PHP/CakePHP/CakePHPのモデルをエンティティとして扱う]]
に対策をまとめた。

** モデルクラスの定数 [#mb895346]
-PHP4では、クラス定数を使うことができないので、連想配列で定数っぽく指定するようにした。
cakecommons/commons_model.php に下記を追加
 // モデル内で使う定数を格納した配列
 var $define = array();
     
 // モデル内の定数の取得
 function c($key) {
     return $this->constant($key);
 }
    
 // モデル内の定数の取得
 function constant($key) {
     return $this->define[$key];
 }
-モデルクラスで、$defineに連想配列で定義しておく。
 var $define = array(
   'SALE_MESSAGE_OPEN' => '%sから販売開始予定です',
   'SALE_MESSAGE_UNFIXED' => '販売日は未定です',
   'SALE_MESSAGE_LAST' => '%sまで販売いたします',
   'SALE_MESSAGE_CLOSE' => '販売終了いたしました',
 );
-定数を取得する場合は、$this->c()メソッドで取得できる。
 $this->c('SALE_MESSAGE_OPEN');

** システム全体で使用するメッセージファイル [#gd2f7c53]
-メッセージに関する設定を下記の中にdefineで指定するようにした。
cakecommons/message.ini.php


** 商品一覧ページ [#j1f4998a]
- (..; 未着手
-カテゴリと商品の関連情報をテーブル設計する。
-カテゴリに属している商品を一覧表示する。
-ページング機能が必要
--decorateで作った骨格を流用できる?
-商品を選択すると商品詳細ページを開く。

** カテゴリメニュー [#xbf5e130]
- (..; 未着手
-サイドメニューにカテゴリリストを表示する。
-部品として作りたい。
--MovableTypeのWidgetみたいにできるか?
-カテゴリは階層があるので、表示中のカテゴリのサブカテゴリのリストを表示する。
-サブカテゴリが存在しなければ、表示中のカテゴリと同階層のカテゴリリストを表示する。

** ビューのパーツ化 [#h0d87fd8]
- (..; 未着手
-viewのelementsを使うとパーツに分けて管理できるみたい。
[[hetimaの日記 - CakePHP の view の elements がアクセスできる変数:http://d.hatena.ne.jp/hetima/20061217/1166318814]]

** ぱんくずリスト [#me13e3c8]
- (..; 未着手
-表示しているカテゴリの階層をぱんくずで表現する。

** 商品をカートに入れる [#n8e23ff6]
- (..; 未着手
-商品詳細ページから数量を指定してカートに入れる。
-カートの内容は、とりあえずセッション情報として保持する。

** カート一覧ページ [#ecbe8333]
- (..; 未着手
-カートの中身を表示する。
-商品の数量変更および削除ができるようにする。

** 届け先入力ページ [#c42ed7bb]
- (..; 未着手
-カート一覧から「レジに進む」で注文手続きに進む。
-届け先と決済方法を入力する。

** 注文内容確認ページ [#w6c17ca5]
- (..; 未着手
-注文する内容を表示する。
-「注文を確定する」で注文情報をDBに格納する。
-購入者にメールを送信する。
--CakePHPでメール送信する方法?

* ふりかえり [#fb0f8d06]

** Keep(よかったこと) [#f214b814]
-共通の処理をcakecommons以下にまとめることができた。
-Log4phpを使うことができたので、ログの監視がやりやすくなった。
-プルダウンの使う方が解った。
-エンティティの概念をうまく吸収できた。

** Problem(わるかったこと) [#s8549b73]
-CakePHPがバージョンアップした際のアップデートが難しい。
--cake本体にも手を入れてしまっているため!
-日本語のメッセージがソースコード内に埋まっているため、多言語対応する時に困る。
-共通部分の実装および検討に時間がかかり、実際の画面の実装が進まなかった。

** Try(次回挑戦) [#tbdb835a]
-cake本体にできるだけ手を入れないようにすること
-アップデート時には元のアーカイブと比較して変更部分のみをマージするようにする。
-CakePHPの多言語対応について調査していく
-次回は、画面実装の見積もりを行うようにして評価する

** イテレーション評価・得点 [#w3dbabaf]
フレームワークを初めて使うときには、共通部分をどのようにして組み込んでいくかの検討に時間がかかることが解った。
プロトタイプ的に作っていくにしても、全体を考えながら進めなければいけないので、共通ロジックの実装を考慮する必要あり。
今回は、当初の目的の画面実装ができなかったので、&color(Red){50点}; (T-T
** 関連ページ [#u78beb3b]
#lsx

#newpage_subdir()

** コメント [#jac86787]
#comment

    ホーム 一覧 単語検索 最終更新 バックアップ リンク元   ヘルプ   最終更新のRSS