【PHP】フレームワーク CakePHP 17ホール目【v2.4】
■ このスレッドは過去ログ倉庫に格納されています
0001nobodyさん
2014/03/01(土) 17:03:24.57ID:8AJ9GD6ECakePHPから派生したLithium(li3)も専スレできるまではここでどうぞ
質問するときはCakePHPのバージョンを書きましょう
※他フレームワークとの比較等はスレ違いです
■本家
http://www.cakephp.org/
APIドキュメント
http://api.cakephp.org/
github - cakephp
http://github.com/cakephp
the Bakery
http://bakery.cakephp.org/
Issue
http://cakephp.lighthouseapp.com/dashboard
CheatSheet[1.2] (PDF)
http://cakephp.org/files/Resources/CakePHP-1.2-Cheatsheet.pdf
■日本語公式
http://cakephp.jp/
フォーラム
http://cakephp.jp/modules/newbb/
cookbook(マニュアル)
[2.x] http://book.cakephp.org/2.0/ja/index.html
[1.3] http://book.cakephp.org/ja
※前スレ
http://kohada.2ch.net/test/read.cgi/php/1378659370/
0506nobodyさん
2014/05/14(水) 23:52:50.14ID:???ありがとう。そういうメリットもあるんですね。
>>505
わからない人にとっては全くわからないんだよね。テストケースのメリット。
俺、gitもテストケースも使ったことないというか使えないので勉強します。
0507nobodyさん
2014/05/15(木) 00:48:57.49ID:???0508nobodyさん
2014/05/15(木) 01:04:25.59ID:???愚者は経験に学ぶと言うけど人間なんて全員愚者だから、がんばって経験を積もう
0509nobodyさん
2014/05/15(木) 02:16:19.81ID:???こういう >>492 時に必要になるんだよ。
例えば1日の区切りが0時じゃなく4時なサービスがあるとしよう。
DateTimeオブジェクトや日時の文字列を受けて、何日かを返すメソッドがあるんだけど、
中身を見たらこりゃひどい実装だなという時、
テストがあれば、中身を書き換えても同じ結果を返す実装にできたとわかりやすい。
0510nobodyさん
2014/05/15(木) 03:48:38.98ID:???テストの話題で盛り上がりやがって
0512nobodyさん
2014/05/15(木) 10:33:38.61ID:???>中身を見たらこりゃひどい実装だなという時、
>テストがあれば、中身を書き換えても同じ結果を返す実装にできたとわかりやすい。
ここが想像できないんだよ。中身(モデル?)が酷い実装っていうけど、
前は動いてたんだよな?それを変更する時に「酷い」が分かるんだろ?
なら、テストも書き直しだと思うんだよ。俺も>>503と同じ疑問を持ってる。
Cakeのバージョンアップではなくとも、仕様が変わればテストも変わるでしょ。
0513nobodyさん
2014/05/15(木) 10:45:22.44ID:???少なくとも単体テストしやすいように設計してれば
仕様を変えた部分の他に影響がないことを保証しやすいんじゃないか
テストが書いてない誰かが作ったソフトウェアを改修する時に
あっち変えたらこっち動かなくなったよみたいな経験ない?
0514nobodyさん
2014/05/15(木) 10:52:06.00ID:???0515nobodyさん
2014/05/15(木) 11:08:32.04ID:???俺も思うな。
一人で開発したことしかないからか、
前に戻したくなることなんてまず無い。
毎回、add、commitする手間の方が面倒な気がするけど。
ただ、いつでも何処にでも戻せる安心感ってのは大きいのかもしれない。
dropboxでも戻せるけどどこに戻せば良いのかすらわからない。
0516nobodyさん
2014/05/15(木) 11:14:00.56ID:???別人だけど、中身ってコードのこと言ってるんだろ。
テストが完璧な仕様を表したものだと仮定すると、
テスト通りに動く限りは、実装コードはいくら変えても構わない、という理屈。
テストコードの方も変える必要がない(というか、変えたら同一の保証ができなくなる)。
もっとも、リファクタリングの過程で、新しいクラスやインターフェースを追加、とかなることが多いから、
その場合は、テストも変えていく必要はあるけど。
0517nobodyさん
2014/05/15(木) 11:25:10.47ID:???まあ趣味で小規模のものならそれでもいいのかな…
0518nobodyさん
2014/05/15(木) 11:31:50.75ID:???一人で開発を数年やってるが仕事でも個人サービスでもgitは重宝してる
過去ログとして何をやったかが残ること。
複数同時に機能開発ができること。
gitなしにはもう生きられない。
テストはControllerのテストは書かない。
それより下位層は書いてる。
自分が書いたコードを忘れたころに重宝してる。
他の機能実装のために、さらに下位層を変更したときに重宝してる。
デプロイツールもなしには生きられんな。
0519nobodyさん
2014/05/15(木) 11:48:03.50ID:???残念ながら商用で10以上の製品を扱ってるんだ・・。
gitの前にSubversionを勉強したこともあったけど、
バージョン管理の利点があまり思いつかないんだよな。バックアップ以外で。
マイナーアップデートしてそれをgitで管理する程度ならいいだろうけど、
開発してたら頻繁に更新するわけだろ?コード間違えも多々ある。
なのに、どのタイミングでadd、commitするか分からんし、
毎回してたら515が言うように面倒だ。
0520nobodyさん
2014/05/15(木) 11:52:50.01ID:???例えばこの2ちゃんの掲示板。
名前とメールアドレスと本文入れて投稿すれば掲載される。
この一連の処理が正しく行われるかのテストを書くわけだろ?
で、そこに「画像を追加できる」という機能が加わったとする。
コントローラーとモデルとビューにコードを追加し、テストも書き直すよな?
なら、またテストのやり直しだ。
0521nobodyさん
2014/05/15(木) 12:25:34.42ID:???テストにもいろいろ種類があるが、ここで書け書け言われてるのは、
単体テストと呼ばれるやつな。
で、単体テストの場合、一連の処理をテストするんじゃなくて、
機能単位でテストする。
俺も理解は甘いから、機能単位と言い切って良いのかわからないけど。
なので >>509 のようなメソッドは、戻り値だけに着目すればよくて、テストが書きやすいんだけど、
コントローラーのテストはちょっと書きにくい。
コントローラーのメソッドはアクションで、実行されたあとの結果がいろいろあるからな。
0522nobodyさん
2014/05/15(木) 12:37:38.37ID:???あえて掲示板ということで、CommentsControllerのaddメソッドのテストで考えてみると
1 必須項目を省いてPOSTしたら、書けてない事
2 書き込み成功していいPOSTなら、書けてる事
3 名前を省略したら「nobodyさん」になる事
もっとあるとは思うけど、addメソッドのテストとして、こんなのを確認するテストを書いたとする。
「画像を追加できる」機能が必須項目じゃなければ、「画像を追加できる」を実装した後も、
このテストは3つの部分は期待通りに動いてることを確認できると思う。
で、画像を追加する投稿についてのテストをいくつか追記して、機能追加が完成できる。
この場合あくまでテストは追記だから、テストは書き直しとは言わないと思う。
画像が必須項目だったとしたら、1と2は書き直しになっちゃうだろうけど、これも微修正って範疇じゃないかと。
0523nobodyさん
2014/05/15(木) 13:17:55.24ID:???commitやマージが便利そうだな。
0524nobodyさん
2014/05/15(木) 13:33:34.19ID:???物凄く分かりやすい!参考になった。
つまり、その1〜3をこれまではブラウザでいちいち実行してたのを
テストコードさえ用意しておけば、自動で成否を出してくれるって事だよね?
それならテストを追加する意味もあるし、すごく便利だと思う。
0525nobodyさん
2014/05/15(木) 16:23:27.92ID:???伝わったようで何よりだけど、あげておとすようで悪いが、
質問してた人が言ってたようなデメリットもやっぱりあるよ。
実装が大きく変われば、さすがにテストも修正というより書き直しになるし、
あとさっきも書いたけどコントローラーはテスト書きにくい。
仕様変更で実装が大きく変わりやすい箇所でもある。
あと >>522 この例でいうと、「画像を追加できる」機能を追加した際、
ぶっちゃけテストなんてなくても1〜3は壊れないような実装になりそうな気がすごいする。
俺としては >>509 のような、ユーティリティ的なライブラリが、テストも書きやすいし恩恵も多いと思う。
実際困ったから書いたんだけど、時間というテストがめんどくさいデータで、
結局動作確認するには、4時丁度とその前後や、逆に0時丁度やその前後を引数に、呼んでみるしかないから、それってテストコードだしな。
で、ユーティリティだからサービスのいろんな箇所で呼ばれてて、ミスったときの影響範囲も広い。
なので、テストコードがないと、修正に及び腰になってしまう。
0526nobodyさん
2014/05/15(木) 16:45:41.71ID:???なんかよく分からなくなってきたな・・・。
コード書いて「こういうイメージ?」って聞こうとしたんだけど、
どう聞けばいいからすら分からず、固まってしまったよw
0527nobodyさん
2014/05/15(木) 19:50:47.49ID:???0528nobodyさん
2014/05/15(木) 19:53:03.77ID:???ちなみにCakePHPにテストという機能がちゃんと用意されてますよ?
だからその事について話し合っているんですよ?
0530nobodyさん
2014/05/15(木) 20:53:28.94ID:???http://book.cakephp.org/2.0/ja/development/testing.html
0532nobodyさん
2014/05/16(金) 13:54:12.18ID:???composerについて教えて下さい。
0533nobodyさん
2014/05/16(金) 14:02:22.96ID:???0534nobodyさん
2014/05/16(金) 14:26:46.96ID:???autoload処理までしてくれるもの
packgistに登録されているものの他に
gitやsvnとかで管理されているもの
zip等で落としてくるもの、PEARとかも管理できる
依存関係の解決や、バージョンアップの追従とかが簡単にできるのがいいね
更新時にスクリプト動かしたりもできるから、さらにいろいろ使えるよ
0535nobodyさん
2014/05/16(金) 14:41:38.71ID:???0536nobodyさん
2014/05/16(金) 21:57:48.54ID:???0537nobodyさん
2014/05/16(金) 22:04:02.91ID:???0539nobodyさん
2014/05/17(土) 02:35:10.07ID:???例えば、
/domain/DB値 みたいな感じで
ちなみに、1.3系
0540nobodyさん
2014/05/17(土) 03:35:24.78ID:???2系では無理。routes.php のタイミングでは ClassRegistry がロードされていない。
1.3系は分からんが、やってみて確かめてみれば?
0541nobodyさん
2014/05/17(土) 03:39:32.10ID:???0542nobodyさん
2014/05/17(土) 05:32:08.69ID:???うーん、たぶんできるんじゃね?
http://book.cakephp.org/2.0/en/development/routing.html#custom-route-classes
まず、カスタムルートクラスを使う。
Cookbookは英語しかないが、これ。
App::uses('CakeRoute', 'Routing/Route');
App::uses('ClassRegistry', 'Utility');
SlugRoute extends CakeRoute{
public function parse($url){
$parse = parent::parse($url);
$hoge = ClassRegistry::init('Hoge');
return $parse;
}
}
こういうカスタムルートクラス書いてみたら、$hogeにHogeのインスタンスがあることまでは確認した。
なお、phpがあるPCと、これ書いてるPHP別なので、上のコードにtypoがあるかもしれない。
カスタムルートクラスでApp::uses('ClassRegistry', 'Utility');することによる弊害があるかどうかは知らない。
0543nobodyさん
2014/05/17(土) 11:47:50.48ID:???それは単にルータのクラスをRouteから変更するだけじゃん。
ルーティングのタイミング(routes.php の読み込み)は一緒だから
Model のインスタンス取得できないんじゃないかってことなんだけど。
0544nobodyさん
2014/05/17(土) 11:54:40.61ID:???ルータのクラスを変更することは
ここでは問題になってないってことを言いたかっただけ。
で、今 routes.php で App::uses('ClassRegistry', 'Utility');
して Model のインスタンス取得したら問題なく動いたわ。
副作用は知らん。
1.3系は ClassRegistry ってないんだっけ?
途中から出来た?
その辺はよく分からん。
0545nobodyさん
2014/05/17(土) 12:16:13.55ID:???あんな感じにできれば便利だなとは思う
0546nobodyさん
2014/05/17(土) 12:21:13.08ID:???もっと初期段階でモデルにアクセスできる仕組みのほうがいい気がする。
他のFWとかのプロセスってこの辺りどうなってんのかな。
俺はCakeしか知らないから。
0547nobodyさん
2014/05/17(土) 12:58:47.14ID:???全体のローダーとルーティングで制限がかかるローダーはタイミングが別なものが多いよ
前者でモデルの読み出しができれば使える感じ
0548nobodyさん
2014/05/17(土) 13:17:23.08ID:???App::uses('ClassRegistry', 'Utility'); で初期段階でモデルにアクセスも出来たし、
あとはカスタムルートクラスで好きなようにパースして返せば、
良い書き方かはおいといて、動きそうな感じはしてるんだけど。
0551nobodyさん
2014/05/18(日) 02:42:01.29ID:???0552nobodyさん
2014/05/18(日) 04:33:21.19ID:???new Hoge()じゃなくてClassRegistry::init('Hoge')が推奨されるのってなんで?
昔コントローラーじゃないところでモデル使うことがある時、
new Hoge()してるって言ったら、だめって言われたことあるんだけど、
まだ初心者だったら理由までは教えてもらえなかったんだよね。
よくわからないまま、ClassRegistry::init()を使うようにだけしてるんだけど、
理由知りたい。
0553nobodyさん
2014/05/18(日) 11:39:16.13ID:???0554nobodyさん
2014/05/18(日) 12:23:32.63ID:???テストを先に書くということですが、
メソッドを先に書く場合もありますか?
0555nobodyさん
2014/05/18(日) 12:34:06.68ID:???記事を書く
記事を見る
記事を削除
の3つのケースを先に書いてテストし実装する
もしくは一つの機能ごとにテストを書く実装する、のどちらが良いのでしょうか。
0556nobodyさん
2014/05/18(日) 18:19:05.82ID:???テストを先に書くことがテスト駆動開発の必須条件の一つだと思うんだけど、
別に原理原則にこたわることもないと思われ。
ただ、教科書的にはまずテストを書いて赤色から発進するのが通則。
>>555
テスト駆動開発は、一般的にはアジャイル開発の一部とされている
(たぶん、そうじゃない場合もあるはずなんだけどあまり記憶に無い)ので
単純なテストからだんだん複雑にして行くことを前提に、
最初は簡単な「記事を書く」テストを書いて実装して
簡単な「記事を見る」テストを書いて実装して、
簡単な「記事を削除」テストを書いて実装して・・・ってことなんじゃないかな?
だけどそれも程度によるだろうから、最初はざっくりアウトライン的に
全体を作って、作りこむに従って単体テストを増やしていったりテスト自体を
詳細にコーディングするってことでいいんじゃないかな?
0558nobodyさん
2014/05/18(日) 23:31:40.02ID:???TDDに限らず、ここで聞くより専門の書籍を一冊買って
それを読んで体系から身につけたほうがいい。
0559nobodyさん
2014/05/19(月) 16:50:44.06ID:???バリデーション自体を中止したいのですが、良い方法はないでしょうか?
以下のようなルールをモデルに書いています。
'image' => array(
array(
'rule' => array('extension', array('jpg', 'jpeg', 'gif', 'png')),
'message' => '拡張子が違います',
'allowEmpty' => true,
)
)
0560nobodyさん
2014/05/20(火) 15:39:04.32ID:RIYxfxGy営業 1−多 顧客
というリレーションがあったとします。
営業 hasMany 顧客 と営業モデルに書いています。
そこで営業コントローラから 「顧客を一件ももっていない営業」をfindする方法がどうしても
思い浮かびません。
どうかヒントをいただけませんでしょうか。
0561nobodyさん
2014/05/20(火) 15:56:13.36ID:???検索条件を
'顧客.id' => null
とすれば行ける気がするのだがどうだろう。
あと、カウンターキャッシュという裏ワザもあるが、
アプリケーション依存になるんで一長一短。
0563nobodyさん
2014/05/21(水) 16:47:46.18ID:???なんかURLのルールが似てる気がする
0565nobodyさん
2014/05/21(水) 19:54:17.38ID:???0566nobodyさん
2014/05/25(日) 12:26:20.21ID:???PofEAAのActiveRecordと違うと思うんだけど。何を元にしてるの?
0567nobodyさん
2014/05/25(日) 13:21:00.24ID:???0568nobodyさん
2014/05/25(日) 14:22:54.54ID:???AppControllerに書かれた$uses、$componentsが使えない(マージされない)問題は
Cake2では直ってるんだっけ?
今確認できないのでどなたか教えてください
0569nobodyさん
2014/05/25(日) 16:32:17.75ID:???Dispatcher でリフレクション呼び出してあれこれゴニョゴニョしてるんで、
多分大丈夫。
正式なアナウンスは知らん。
0571nobodyさん
2014/05/26(月) 21:17:51.86ID:???0572nobodyさん
2014/05/26(月) 21:34:55.75ID:???0573nobodyさん
2014/05/28(水) 12:20:55.53ID:???ルーティングってどう書けばいいですかね?
/hoge/ →Categoryモデルのname「hoge」
/hoge/news/ →Newsモデルのcategory_nameが「hoge」
/hoge/news/detail/1 →Newsモデルのidが1でcategory_nameが「hoge」
こういう場合、hogeの箇所(カテゴリ名)が不特定文字列なので
どういう書き方をすればいいか悩んでいます。cake2系です。
0574nobodyさん
2014/05/28(水) 12:29:00.97ID:???Router::routes(array('/:category/:controller/'));
Router::routes(array('/:category/:controller/detail/:id'));
でどう?
0575nobodyさん
2014/05/28(水) 12:33:07.08ID:???3つ目のURLパターンにおいてIDは数値と決まっているなら
Router::routes(array('/:category/:controller/:id'), array(), array('id' => '[0-9]+'));
とすることで
/hoge/news/1
をマッチさせることが出来ると思う。
0576573
2014/05/28(水) 13:36:48.07ID:???ありがとうございます。この方法ですが、
他のコントローラーと共存させたい場合はどうなるのでしょうか?
/contacts/ お問い合せ用のコントローラー
/faqs/ FAQ用のコントローラー
などがサイトに存在する場合、おかしくなるような気が・・。
そういう場合は、固定のコントローラーを
ルーティングに書いていけばいいんですかね?
Router::routes(array('/contacts/:action'), array('controller' => 'contacts'));
0577nobodyさん
2014/05/28(水) 13:55:25.16ID:???ルーティングは単純な正規表現を先頭からマッチさせていくだけ。
で、最後の最後に通常のマッチングがコアの方に用意されている。
0578nobodyさん
2014/05/28(水) 13:56:01.83ID:???0579nobodyさん
2014/05/28(水) 13:56:49.69ID:???>ルーティングに書いていけばいいんですかね?
>Router::routes(array('/contacts/:action'), array('controller' => 'contacts'));
そうですね。
0580573
2014/05/28(水) 15:29:39.46ID:???ということは、固定のコントローラーは全てルーティングに書く必要があるんですね。
そうなるとあまり利便性が良くないですね。
0581nobodyさん
2014/05/28(水) 17:12:42.77ID:???http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html
0582nobodyさん
2014/05/28(水) 20:12:28.98ID:???カテゴリ名を自由にするってことは、特定の文字を禁止にするんだろうから、
それを表現できるパターンを第3パラメータに書けば良いと思うよ。
たとえば ["member", "user"] というコントローラを作るんなら
$route = '/:controller/:action/*';
$default = array();
$options = array('controller' => '(member|user)');
Router::connect(compact('route', 'default', 'options'));
あと、アクションを設定しない場合に index を適用させるなら
$route = '/:controller';
$default = array('action' => 'index');
Router::connect(compact('route', 'default'));
を最初に加えておく。
あとすまん、
上で Router::routes() っていうのは Router::connect() の間違いだった。すまん。
0583nobodyさん
2014/05/28(水) 20:13:54.99ID:???lft, rght はIDじゃないよ。
TreeBehavior のアルゴリズムを理解するのにとっておきの記事
http://blog.xao.jp/blog/cakephp/understanding-of-nested-sets-model-for-treebehavior-of-cakeph/
0586nobodyさん
2014/05/29(木) 01:00:35.02ID:???テーブル関係ないビジネスロジックをどこに書くか迷って、コンポーネントに書いてたけど
モデルに書いた方がいいんだろうか?
0587nobodyさん
2014/05/29(木) 01:27:10.16ID:???ビジネスロジックをモデルに書くのは常識だ。
コンポーネントに書いたほうが良いなんて聞いたこと無い。
Rails も Cake もその点においては何も騙してねーと思うよ?
0588nobodyさん
2014/05/29(木) 08:11:31.86ID:???そういう場合にRailsの1モデル-1テーブル形式は破綻してるのは確か。
0589nobodyさん
2014/05/29(木) 08:25:24.09ID:???http://book.cakephp.org/2.0/ja/models.html
とあるせいで、モデル=テーブルに紐付く(原則として)と思ってたよ
市販の解説書も同じような感じで書いてる
0590nobodyさん
2014/05/29(木) 08:44:24.60ID:???モデルの中で他のモデルをClassRegistry::initとかやりたくないんだよ
コントローラに書きたくなければコンポーネントになる
0591nobodyさん
2014/05/29(木) 10:03:02.00ID:veg5U4SWModelじゃだめって理由でComponentに置く発想がおかしい
0592nobodyさん
2014/05/29(木) 10:04:39.91ID:???Controllerの冒頭で配列に入れるだけで$thisで使えるんだから
0593nobodyさん
2014/05/29(木) 10:18:58.89ID:???データベーステーブルと(さらにはコントローラとも)1対1対応しなきゃいけないように見えるから勘違いしやすいんだよな
Railsは1つのモデルに関するロジックは"モデル"クラスに書けるけど
Table Data GatewayのCakeはこれすらコントローラやヘルパーに溢れ出やすい印象
複数"モデル"が絡むときに簡易サービス層として利用されやすいのがコンポーネントなのかな
コントローラから呼びやすいしファットコントローラの一番楽な回避策だろうし
初心者でも(本来の広い意味での)モデルの中にサービス層を作りやすい実装や解説にしておいてくれるとありがたいんだけど
0594nobodyさん
2014/05/29(木) 10:27:52.09ID:veg5U4SWなんだその理由ww
0596nobodyさん
2014/05/29(木) 11:35:25.87ID:Kdl2SKiZ>似て非なるテーブルに同じ処理をしたい場合
これはビヘイビアがいい気がする。
0597nobodyさん
2014/05/29(木) 13:26:17.97ID:???結論は出なかった
0598nobodyさん
2014/05/29(木) 13:48:42.54ID:???>>593 のいうサービス層が必要になる規模は、CakePHPではちょっと対象外なんじゃないかと思ってる。
CakePHPの中の人がどう思って作ってるかはしらんけど。
0599nobodyさん
2014/05/29(木) 15:11:21.10ID:???$useTable = false の別のモデルを作った方がずっと楽だと思うんだが。
コントローラから直接参照できる点は一緒。
データのセット、バリデーション、フォーム値の復元。
使うモデルを $hasOne とか入れとけば ClassRegisry::init も呼ぶ必要ない。
0600nobodyさん
2014/05/29(木) 15:24:59.72ID:???0601nobodyさん
2014/05/29(木) 15:34:31.80ID:???Modelの下にサブディレクトリ切ってAppでパス通すのもありだと思う。
Lib は他で作ったライブラリを置く場所にしてる。
コンポーネントはコントローラの処理を助けることが限定されている場合しか書く意味ない。
もちろん、そういうロジックだけならコンポーネントはすれば良い。
0602nobodyさん
2014/05/29(木) 16:13:20.58ID:???会員制サイトだと、以下のような構成がよくあるが、
会員
└日記
└お気に入り
└掲示板の作成や投稿
会員を削除すると、その下の投稿内容も削除しないとおかしい(と俺は思う)
だから俺は、管理画面で会員を削除したら、user_idがあるモデルは全て削除している。
削除はコントローラーに書いてる。
0604nobodyさん
2014/05/29(木) 16:37:36.60ID:???hasManyでdependentをtrueだな。
俺も基本はそうしてるんだけど、>>602のに「画像」がある場合は困る。
各テーブルを参照して画像情報を取得し、削除していく必要がある。
0605nobodyさん
2014/05/29(木) 16:50:52.43ID:???■ このスレッドは過去ログ倉庫に格納されています