このBlogをしばらく更新をしていませんでしたが、実は独自ドメインでブログを始めています。
プログラミンはもちろん、アフィリエイトなどのマネタイズに関することも書いています。
基本は、このブログと同じく、自分が学んだこと、ぶつかった問題への対処法などを書いていきます。
では、今後ともよろしくお願いいたします。
Webで食う技術を学ぶメディア、WebFood
2016年4月14日木曜日
CakePHPとRailsの比較
ずっとCakePHPを使ってきましたが、周りにRailsを使え使えという人が多かったので、ここ1年くらいはRails漬けです。
簡単にですが、両者を比較してみたいと思います。
簡単にですが、両者を比較してみたいと思います。
CakePHPのメリット
- エンジニアの数が多く採用がしやすい
- 環境構築が簡単
- PHPは独特な概念が少ないので習得しやすい
Railsのメリット
- エンジニアのレベルが高く、一人でなんでもできちゃう人が多い
- オープンソース活動が活発でライブラリがたくさんあるし、情報も多い
- 独特な概念は多いが、その分コードが綺麗になる
- コードが少なくなるのでメンテナンスがしやすい
ほんとにざっくりいうとこんな感じですね。
正直、CakePHPにある程度慣れた人には、Railsを触ってみることをお勧めします。
MVCなどの概念はとても似ているので、理解はしやすいですし、この手のフレームワークの本家はRailsなので、学ぶと色々と腑に落ちること多いと思います。これって、こういう目的なのかぁ、と思うことが多いです。
とはいえ、これだけの比較だと足りないと思いますので、もっと詳しく比較した記事をご紹介します。
2014年7月9日水曜日
[CakePHP]v3.0.0-alpha1導入@XAMPP
ここを参考にした。
http://book.cakephp.org/3.0/en/installation.html
以下のエラーが。
こんなエラーが。。。
※localhostが衝突したのでport指定した。
とりあえず、起動しました。あとはデータベースの設定
http://book.cakephp.org/3.0/en/installation.html
1.コンポーザやってみると。
composer create-project -s dev cakephp/app
以下のエラーが。
Warning: This development build of composer is over 30 days old. It is recommended to update it by running "/usr/local/bin/composer self-update" to get the latest version.
Installing cakephp/app (dev-master d15c9b13b6088a4bf3d52a3342fbce878a6cc3a5)
- Installing cakephp/app (dev-master master)
Cloning master
Created project in /Users/araky/git/test03/app
Loading composer repositories with package information
Installing dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Installation request for cakephp/cakephp 3.0.*-dev -> satisfiable by cakephp/cakephp[3.0.x-dev].
- cakephp/cakephp 3.0.x-dev requires ext-intl * -> the requested PHP extension intl is missing from your system.
2.intlをダウンロード
http://pecl.php.net/package/intlgunzip intl-3.0.0.tgz tar xvf intl-3.0.0.tar
3.phpize
/Applications/XAMPP/bin/phpize
4.configure
./configure --with-php-config=/Applications/XAMPP/bin/php-config-5.5.9
こんなエラーが。。。
configure: error: Unable to detect ICU prefix or no failed. Please verify ICU install prefix and make sure icu-config works.
5.icuをinstall
brew install icu4c
6.もう一度configure
./configure --with-php-config=/Applications/XAMPP/bin/php-config-5.5.9 --with-icu-dir=/usr/local/Cellar/icu4c/52.1
7.sudo make
8.sudo make test
なんかFailでてるけどいいや。
===================================================================== TEST RESULT SUMMARY --------------------------------------------------------------------- Exts skipped : 0 Exts tested : 59 --------------------------------------------------------------------- Number of tests : 388 357 Tests skipped : 31 ( 8.0%) -------- Tests warned : 0 ( 0.0%) ( 0.0%) Tests failed : 22 ( 5.7%) ( 6.2%) Expected fail : 0 ( 0.0%) ( 0.0%) Tests passed : 335 ( 86.3%) ( 93.8%) --------------------------------------------------------------------- Time taken : 36 seconds ===================================================================== ===================================================================== FAILED TEST SUMMARY --------------------------------------------------------------------- Bug #58756: w.r.t MessageFormatter [tests/bug58756_MessageFormatter.phpt] IntlCalendar::getDayOfWeekType() basic test [tests/calendar_getDayOfWeekType_basic.phpt] asort() [tests/collator_asort.phpt] compare() [tests/collator_compare.phpt] get_locale() icu >= 4.8 [tests/collator_get_locale2.phpt] collator_get_sort_key() [tests/collator_get_sort_key.phpt] sort() [tests/collator_sort.phpt] sort_with_sort_keys() [tests/collator_sort_with_sort_keys.phpt] IntlDateFormatter: several forms of the calendar arg [tests/dateformat_create_cal_arg.phpt] IntlDateFormatter::formatObject(): IntlCalendar tests [tests/dateformat_formatObject_calendar.phpt] IntlDateFormatter::formatObject(): DateTime tests [tests/dateformat_formatObject_datetime.phpt] datefmt_format_code() (5.3+, ICU >= 50) [tests/dateformat_format_50+.phpt] datefmt_format_code() and datefmt_parse_code() (ICU >= 50) [tests/dateformat_format_parse_50+.phpt] IntlDateFormatter: setCalendar()/getCalendar()/getCalendarObject() [tests/dateformat_get_set_calendar.phpt] IntlDateFormatter: get/setTimeZone() [tests/dateformat_get_set_timezone.phpt] IntlDateFormatter: several forms of the timezone arg [tests/dateformat_timezone_arg_variations.phpt] numfmt_format() icu >= 4.8 [tests/formatter_format2.phpt] locale_get_display_name() ICU >= 50 [tests/locale_get_display_name_50+.phpt] locale_get_display_script() icu >= 49 [tests/locale_get_display_script3.phpt] MessageFormat accepts IntlCalendar args [tests/msgfmt_format_intlcalendar.phpt] msgfmt_parse() tests [tests/msgfmt_parse.phpt] IntlTimeZone::getDisplayName(): type parameter (ICU >= 49) [tests/timezone_getDisplayName_variant2-49+.phpt] =====================================================================
9.sudo make install
10.php.ini編集
extension=intl.so
11.改めて
composer create-project -s dev cakephp/app
12. Cake のserver起動。Railsっぽい。
Console/cake server -p 9999
※localhostが衝突したのでport指定した。
とりあえず、起動しました。あとはデータベースの設定
2014年6月30日月曜日
[CakPHP]ControlloerでsetするとDebugKitのVariablesタブで捕捉されないことがある
※version2.4.9の話
ControllerのCallback関数には、
Controller::beforeFilter()
Controller::beforeRender()
Controller::afterFilter
があるけど、beforeRenderとafterFilterでController::setしてもDebugKitのVariablesタグで捕捉されることはない。afterFilterでsetしてもViewで使えないので全く意味はないが。
beforeRenderでsetしたいケースはあると思う。たとえば、Authの情報をどのページでもsetしているが、logout画面ではする必要がない(したくない)ので、その場合はbeforeRenderにset処理を入れておく。すると、beforeRender以前にlogoutのロジックが終わっているので、Auth情報はセッションからなくなっているので、setせずに済む。
これをbeforeFilterでsetしていると、logout処理の前でセッションからAuth情報がある状態なのでsetされてしまい、View画面で使われてしまったりする。「ログアウトしました。」画面なのに、「マイページ」とか表示されてたりする。
話はそれたけど、beforeRenderでController::setしてもDebugKitのVariablesからは見えないけど、ViewではきちんとRenderされます。
ControllerのCallback関数には、
Controller::beforeFilter()
Controller::beforeRender()
Controller::afterFilter
があるけど、beforeRenderとafterFilterでController::setしてもDebugKitのVariablesタグで捕捉されることはない。afterFilterでsetしてもViewで使えないので全く意味はないが。
beforeRenderでsetしたいケースはあると思う。たとえば、Authの情報をどのページでもsetしているが、logout画面ではする必要がない(したくない)ので、その場合はbeforeRenderにset処理を入れておく。すると、beforeRender以前にlogoutのロジックが終わっているので、Auth情報はセッションからなくなっているので、setせずに済む。
これをbeforeFilterでsetしていると、logout処理の前でセッションからAuth情報がある状態なのでsetされてしまい、View画面で使われてしまったりする。「ログアウトしました。」画面なのに、「マイページ」とか表示されてたりする。
話はそれたけど、beforeRenderでController::setしてもDebugKitのVariablesからは見えないけど、ViewではきちんとRenderされます。
2014年6月7日土曜日
[CakePHP]CakeDC/migrationsの微妙な仕様
ここによるとModelが存在しないテーブルのmigrationは以下のように-fをつけてあげるとできる。これをつけないと、差分として検知されない。
ここでは例えば、Aというテーブルを作成した場合とする。
①
cake Migrations.migration generate -f
このコマンドから始まるプロンプトを進めて行くと、以下のように
②
Do you want update the schema.php file? (y/n)
schema.phpを更新するか聞かれて、自分はいつも通り、yを選択する。
で、次にDB定義変更をしてmigrationをする機会が訪れたとする。
今度は普通にModelが存在するテーブルBだったので、以下のように-fはつけない。
③
cake Migrations.migration generate
そうすると何が起こるかというと、①で作成したテーブルAをdropするmigrationが作成されてしまう。
なぜかというと、②でも-fが有効になっているらしく、ここで生成されるschema.phpにはテーブルAが入ってしまう。migrationの仕組みは現実のDB定義とschema.phpを比較して差分をmigrationファイルとする。なので、③で-fをつけないのからモデルのないテーブルは検知されないため、schema.phpにあるAテーブルは、現実のDBには存在しないよ、となり、じゃあ削除するマイグレーションファイル作りますね、と判断してしまうのだ。
イケてないですね。
なので、 -fをつける場合は②はnを選択したほうがよさそうですね。
ここでは例えば、Aというテーブルを作成した場合とする。
①
cake Migrations.migration generate -f
このコマンドから始まるプロンプトを進めて行くと、以下のように
②
Do you want update the schema.php file? (y/n)
schema.phpを更新するか聞かれて、自分はいつも通り、yを選択する。
で、次にDB定義変更をしてmigrationをする機会が訪れたとする。
今度は普通にModelが存在するテーブルBだったので、以下のように-fはつけない。
③
cake Migrations.migration generate
そうすると何が起こるかというと、①で作成したテーブルAをdropするmigrationが作成されてしまう。
なぜかというと、②でも-fが有効になっているらしく、ここで生成されるschema.phpにはテーブルAが入ってしまう。migrationの仕組みは現実のDB定義とschema.phpを比較して差分をmigrationファイルとする。なので、③で-fをつけないのからモデルのないテーブルは検知されないため、schema.phpにあるAテーブルは、現実のDBには存在しないよ、となり、じゃあ削除するマイグレーションファイル作りますね、と判断してしまうのだ。
イケてないですね。
なので、 -fをつける場合は②はnを選択したほうがよさそうですね。
[SublimeText] .sublime-projectの属性はシングルクオテーションじゃなくてダブルクオテーションじゃなきゃだめ。
※Sublime Text3の話
"xdebug":
{
"max_children": 128,
"max_depth": 5,
"max_data": 512,
"debug_layout":
[
{
'rows': [0.0, 1.0],
'cols': [0.0, 0.6180212590826522, 1.0],
'cells': [[0, 0, 1, 1], [1, 0, 2, 1]]
}
]
}
こんな感じでシングルクオテーション使ってたら、
Error trying to parse project: Expected value in
というエラーが発生した。なのでダブルクオテーションにしたら直った。
2014年6月6日金曜日
[CakePHP]find()のオプションのpageはlimitと併用しないと恐ろしい事に。。。
※CakePHP2.4.9のお話。
こんな感じで、特定の条件全てのレコードに対してある処理をするバッチを作っていて、1pageあたりの数はデフォルト値を当然使ってくれるだろうと思っていたんだけど、これを実行したら、なかなか処理終わらずおかしいなと思ってたら、あるテーブルにありえない数のレコードがインサートされてる。。。無限ループ状態になっていました。あわてて、ApacheとMySQLをシャットダウンして、止めた。
というわけで、デバッグしたら、limitを明示的に定義していないと、実際SQLで使われるoffsetとlimitに値が入らないってことがわかった。
model.php 2942行目
$page = 1;
do{
$ids = $this->find('list',array(
'page' => $page,
'fields' => array('user_id'),
'conditions' => //ある条件
));
//ある処理
$page++;
}while (!empty($ids));
こんな感じで、特定の条件全てのレコードに対してある処理をするバッチを作っていて、1pageあたりの数はデフォルト値を当然使ってくれるだろうと思っていたんだけど、これを実行したら、なかなか処理終わらずおかしいなと思ってたら、あるテーブルにありえない数のレコードがインサートされてる。。。無限ループ状態になっていました。あわてて、ApacheとMySQLをシャットダウンして、止めた。
というわけで、デバッグしたら、limitを明示的に定義していないと、実際SQLで使われるoffsetとlimitに値が入らないってことがわかった。
model.php 2942行目
if ($query['page'] > 1 && !empty($query['limit'])) {
$query['offset'] = ($query['page'] - 1) * $query['limit'];
}
なので、以下のようにlimitを明示的に指定して直った。恐ろしや〜。
$page = 1;
do{
$ids = $this->find('list',array(
'page' => $page,
'limit' => 20,
'fields' => array('user_id'),
'conditions' => //ある条件
));
//ある処理
$page++;
}while (!empty($ids));
[Composer]installer-pathsの優先順位について
Composerでここで説明されているように、packageごとにinstallされるpathをカスタマイズできるんだけど、なかなか反映されなくて困った。
こんな感じだったんだけど、上記のsome-package(もちろん仮名ね)っていうpluginもcakephp-pluginなんだけど、上にあるcakephp-plugin用のpathが先に適用されてしまったからでした。
なので、以下みたいにしたら適用されました。
"extra": {
"installer-paths": {
"plugins/{$name}/": ["type:cakephp-plugin"],
"app/Plugin/{$name}/": ["somevendor/some-package"]
}
}
こんな感じだったんだけど、上記のsome-package(もちろん仮名ね)っていうpluginもcakephp-pluginなんだけど、上にあるcakephp-plugin用のpathが先に適用されてしまったからでした。
なので、以下みたいにしたら適用されました。
"extra": {
"installer-paths": {
"app/Plugin/{$name}/": ["somevendor/some-package"],
"plugins/{$name}/": ["type:cakephp-plugin"]
}
}
2014年6月5日木曜日
[CakePHP]test.phpのCode coverageが表示されない件
テストケースのファイル名をPost01Test.phpみたいに、番号をつけたらcode coverageが表示されなくなった。テスト自体は正常に実行することができるのに。
なので、番号をつけるのをやめてPostTest.phpに戻した。
なので、番号をつけるのをやめてPostTest.phpに戻した。
2014年6月4日水曜日
[CakePHP]find('list')はDISTINCT使えないのね。
$this->Comment->find('list',array(
fields' => array('DISTINCT user_id'),
'conditions' => $conditions,
));
こんな感じでやったら、以下のようなエラーが。
PDOEXCEPTION
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DISTINCT `Comment. user_id` FROM `test`.`comments` AS `Comment` WHERE 1 = 1 ' at line 1
このサイトによると、DISTINCTってSELECTの直後に来ないといけないいたい。でもCakePHPのfind('list')ってデフォルトでは、SELECTの直後でIDを指定しているので、DISTINCTがその後になってしまうんですよね。
なので、group byを使うといいみたい。
$this->Comment->find('list',array(
fields' => array('user_id'),
'conditions' => $conditions,
'gruop' => 'user_id'
));
※Group Byの豆知識
デフォルトだとGROUP BYで指定されたカラムの昇順になる。いきなり順番変わってびっくりした。ORDER BY を使って任意のカラムの昇順、降順を指定できる。
2014年5月29日木曜日
[CakePHP]Controllerのテストで主要モデル以外のモデルのモックを作る方法
※CakePHP2.4.9の話
例えば、AmazonsControllerのテストの場合、
AmazonsControllerTest.php内
主要モデル(コントローラー名に名前が入るモデル)のAmazonモデルの場合は、こんな感じでモックを生成できる。(hardToTestというメソッドのモックを作りたい時)
でも、それ以外のモデル、例えば、Amazonモデルにアソシエーションで紐づくモデルやControllerの処理内でloadModel()したモデル、さらにそれにアソシエーションに紐づくモデルetcはこのやりかたで生成できない。
上記でいう、6行目のexpects()で下記のエラーが発生する。
Error: Call to a member function expects() on a non-object
これに対処する方法のひとつにテスト対象のControllerの$usesにモックを生成したいモデルを入れる、というものもある。ようは、モック化対象のモデルを主要モデルの一つにしちゃうという方法だ。これなら上記のような形で生成できる。
でもそもそもテストのためにプロダクトのコードに手を入れるのってやだよね。
そんな場合は、getMockForModel()を使う。これで簡単にControllerのテスト内で任意のモデルのモックを生成できる。
上記で登場するVoteモデルはちなみにAmazonモデルには直接アソシエーションで紐づいていないモデルだ。Controllerの処理内でloadModelされるItemというModelにアソシエーションで紐づいているモデルである。
でも上記のコードでモックを生成することができる。
注意点としては、かならず1行目でControllerのモックを生成しておく必要があること。
余談だが、上記の$this->Controllerて変数はどんな変数名にしてもOK。$Amazonsにしてもいいし$aでも$bでもOK。generate()メソッドは自動的に$this->Controllerを生成してくれるみたいです。※参考 CakePHP 2.xのtestActionをちゃんと理解しよう
もう一つ余談ですが、当然ですが、モック化したメソッド以外のメソッドは本物のメソッド使ってくれるみたいですね。
例えば、AmazonsControllerのテストの場合、
AmazonsControllerTest.php内
$this->controller = $this->generate('Amazons', array(
'models' => array(
'Amazon' => array('hardToTest')
)
));
$this->controller->Amazon->expects($this->once())
->method('hardToTest')
->will($this->returnValue(true));
主要モデル(コントローラー名に名前が入るモデル)のAmazonモデルの場合は、こんな感じでモックを生成できる。(hardToTestというメソッドのモックを作りたい時)
でも、それ以外のモデル、例えば、Amazonモデルにアソシエーションで紐づくモデルやControllerの処理内でloadModel()したモデル、さらにそれにアソシエーションに紐づくモデルetcはこのやりかたで生成できない。
上記でいう、6行目のexpects()で下記のエラーが発生する。
Error: Call to a member function expects() on a non-object
これに対処する方法のひとつにテスト対象のControllerの$usesにモックを生成したいモデルを入れる、というものもある。ようは、モック化対象のモデルを主要モデルの一つにしちゃうという方法だ。これなら上記のような形で生成できる。
でもそもそもテストのためにプロダクトのコードに手を入れるのってやだよね。
そんな場合は、getMockForModel()を使う。これで簡単にControllerのテスト内で任意のモデルのモックを生成できる。
$this->Controller = $this->generate('Amazons');
$this->getMockForModel('Vote', array('hardToTest'))
->expects($this->any())->method('hardToTest');
上記で登場するVoteモデルはちなみにAmazonモデルには直接アソシエーションで紐づいていないモデルだ。Controllerの処理内でloadModelされるItemというModelにアソシエーションで紐づいているモデルである。
でも上記のコードでモックを生成することができる。
注意点としては、かならず1行目でControllerのモックを生成しておく必要があること。
余談だが、上記の$this->Controllerて変数はどんな変数名にしてもOK。$Amazonsにしてもいいし$aでも$bでもOK。generate()メソッドは自動的に$this->Controllerを生成してくれるみたいです。※参考 CakePHP 2.xのtestActionをちゃんと理解しよう
もう一つ余談ですが、当然ですが、モック化したメソッド以外のメソッドは本物のメソッド使ってくれるみたいですね。
2014年5月26日月曜日
[CakePHP]deleteAllはcounterCache更新してくれないみたいね。
※CakePHP2.4.9の話
これは古い記事だけど、こういう対処法があるんだね。
counterCache and deleteAll: How to Make Them Friends
※追記
すみません。引数でcallbackを動かすか指定できるので、それをtrueにするとcoutercacheも更新されます。
http://book.cakephp.org/2.0/en/models/deleting-data.html#deleteall
これは古い記事だけど、こういう対処法があるんだね。
counterCache and deleteAll: How to Make Them Friends
※追記
すみません。引数でcallbackを動かすか指定できるので、それをtrueにするとcoutercacheも更新されます。
http://book.cakephp.org/2.0/en/models/deleting-data.html#deleteall
2014年5月18日日曜日
[Bootstrap]collapseでクリックしたらdata-targetではなくhrefを使うべし。
※Bootstrap 3.1.1のお話。
しかし、iphone5cで試すと、開閉しない。
クリック(iphoneだとtap)する要素がbuttonタグの場合や、classに.btnなどがついている場合、type="button"がついている場合は開閉する。しかし、ただのaタグの場合は開閉しない。
aタグでtype="button"やclass="btn"をつけたくない場合は、data-target="#demo"ではなく、href="#demo"をつけるとうまく動く。
両方つけてしまうと、対象の#demoが画面トップにくようスクロールしてしまう。
まず、http://getbootstrap.com/javascript/#collapseでは、以下のように説明されていて、開閉したい要素のidをdata-targetで指定するように書いてある。
たとえば data-target="#demo" といったような感じだ。
たとえば data-target="#demo" といったような感じだ。
Via data attributes
Just add data-toggle="collapse" and a data-target to element to automatically assign control of a collapsible element. The data-target attribute accepts a CSS selector to apply the collapse to. Be sure to add the class collapse to the collapsible element. If you'd like it to default open, add the additional classin.
しかし、iphone5cで試すと、開閉しない。
クリック(iphoneだとtap)する要素がbuttonタグの場合や、classに.btnなどがついている場合、type="button"がついている場合は開閉する。しかし、ただのaタグの場合は開閉しない。
aタグでtype="button"やclass="btn"をつけたくない場合は、data-target="#demo"ではなく、href="#demo"をつけるとうまく動く。
両方つけてしまうと、対象の#demoが画面トップにくようスクロールしてしまう。
2014年5月13日火曜日
[CakePHP]Validation の'required' => trueは外部キーにはいれないほうがいい。
なんでかというと、$Model->saveAssociated()等でassociation先のモデルと同時に保存する場合、外部キーを自動的に補ってくれる。
でもvalidationの処理が走るのは、外部キーを補う前なので、'required' => trueになってしまい、validation errorが発生してしまうから。
※CakePHP2.4.9の話
でもvalidationの処理が走るのは、外部キーを補う前なので、'required' => trueになってしまい、validation errorが発生してしまうから。
※CakePHP2.4.9の話
[CakePHP]Validationってそもそも配列にfieldの添字がないと発火しないんだね。
※CakePHP2.4.9のお話
何が言いたいかって、例えば以下のようなvalidationを設定している時。
下記みたいにvalidation対象のuser_idが無い配列を保存しようとしたら、notEmptyが発生すると思ていたんだけど、発生せずに保存しちゃった。user_idにはDBでフォルトの0が入っていた。
要するに、validationするには対象のフィールドの添字が配列内に存在しないと発火しないのね。
※追記
色々実験してわかったけど、以下みたいに'required' => trueを入れると添字がない場合にvalidation errorを発生させてくれる。
何が言いたいかって、例えば以下のようなvalidationを設定している時。
public $validate = array(
'user_id' =>array(
'rule' => 'notEmpty',
'message' => 'このフィールドは必ず入力してください。',
),
),
);
下記みたいにvalidation対象のuser_idが無い配列を保存しようとしたら、notEmptyが発生すると思ていたんだけど、発生せずに保存しちゃった。user_idにはDBでフォルトの0が入っていた。
array( 'theme_id'=> '22' )
要するに、validationするには対象のフィールドの添字が配列内に存在しないと発火しないのね。
※追記
色々実験してわかったけど、以下みたいに'required' => trueを入れると添字がない場合にvalidation errorを発生させてくれる。
public $validate = array(
'user_id' =>array(
'rule' => 'notEmpty',
'message' => 'このフィールドは必ず入力してください。',
'required' => true, ), ), );
'required' => trueの不思議なのって、どのvalidationの種類にも入れられるので、例えばemailの形式を求めるvalidationに入れた場合、メッセージは「emailの形式で入れて下さい」みたいに出るんだよね。notEmptyだったらわりと自然なメッセージになるけど。
2014年5月7日水曜日
[CakePHP]Fatal Error Error: Cannot redeclare class ThemesItemFixture
CakePHPでブラウザ上からのUNITテストをしていたらこんなエラーが出ました。
いくつかのテストファイルをまとめている「All tests」実行時のみ発生しました。
単体でそれぞれでテストを実行した場合は発生しませんでした。
以下のように修正したら直りました。なんか衝突してたみたいですね。
単体のファイルの実行だとどちらもOKというのが不思議な感じがしますが。
before
afiter
いくつかのテストファイルをまとめている「All tests」実行時のみ発生しました。
単体でそれぞれでテストを実行した場合は発生しませんでした。
以下のように修正したら直りました。なんか衝突してたみたいですね。
単体のファイルの実行だとどちらもOKというのが不思議な感じがしますが。
before
public $fixtures = array(
'app.themesitem'
);
afiter
public $fixtures = array(
'app.themes_item'
);
2014年5月6日火曜日
[CakePHP]外部サービスのAPIを使ったdatasourceのテスト
自分はAmazon AssociateのAPIを使ったデータソースを作った。
でもこのあたりのテストを書こうとしてたら問題がおこった。
以下を参考にしたら解決策がわかった。
[PHP] CakePHP の $useDbConfig にはまった(備忘録)
フィクスチャの作成
単純にdatabase.php内に作成したデータソースの接続設定に対応する設定を作ってあげればOKです。
例えば、database.php内に以下のようなデータソースの設定を追加したなら、
合わせてdatabase.php内に以下のようなデータソースを設定する必要があります。
変数名は上記のように、$test_[テストしたい設定名]にしなくてはなりません。
これで終わりです。fixtureを作成する必要もありません。
あとはテストを書くだけです。
でもこのあたりのテストを書こうとしてたら問題がおこった。
MISSINGTABLEEXCEPTION Table amazons for model Amazon was not found in datasource test.こんなエラーが発生した。
以下を参考にしたら解決策がわかった。
[PHP] CakePHP の $useDbConfig にはまった(備忘録)
フィクスチャの作成
単純にdatabase.php内に作成したデータソースの接続設定に対応する設定を作ってあげればOKです。
例えば、database.php内に以下のようなデータソースの設定を追加したなら、
public $amazon = array( 'datasource' => 'AmazonSource' );
合わせてdatabase.php内に以下のようなデータソースを設定する必要があります。
public $test_amazon = array( 'datasource' => 'AmazonSource' );
変数名は上記のように、$test_[テストしたい設定名]にしなくてはなりません。
これで終わりです。fixtureを作成する必要もありません。
あとはテストを書くだけです。
2014年4月23日水曜日
[CakePHP]AppControllerのbeforeFilterが2回以上呼び出されている時。
「Missing View」のエラーがでる時なんかは、継承しているAppControllerのbeforeFilterが2回以上呼ばれていることがわかった。
また、それぞれのControllerでbeforeFilterを完全に上書きoverrideしている時でも(つまり、parent::beforeFilter();を書かないケース)、Missing View等のエラー画面を出すのにAppControllerのbeforeFilterが呼ばれてしまう。(せっかく完全上書きしてAppControllerのbeforeFilterを使わないようにしているのに)
具体的に言うと、AppControllerでは各Controllerで共通で使う、cookieを使った自動ログイン処理を入れたりするが、UserControllerだけはlogout処理等があるため自動ログインしたくない場合などに困る。(logout処理した直後に自動ログイン処理が走ってしまう。cookieはresponseが完了するまで反映されないため)
また、それぞれのControllerでbeforeFilterを完全に上書きoverrideしている時でも(つまり、parent::beforeFilter();を書かないケース)、Missing View等のエラー画面を出すのにAppControllerのbeforeFilterが呼ばれてしまう。(せっかく完全上書きしてAppControllerのbeforeFilterを使わないようにしているのに)
具体的に言うと、AppControllerでは各Controllerで共通で使う、cookieを使った自動ログイン処理を入れたりするが、UserControllerだけはlogout処理等があるため自動ログインしたくない場合などに困る。(logout処理した直後に自動ログイン処理が走ってしまう。cookieはresponseが完了するまで反映されないため)
2014年4月6日日曜日
[Composer]不要なパッケージを削除する方法。
ここを参考に。
uninstall command please.
1. まずcomposer.json から不要なパッケージの行を削除。
2. composer update xx/yy を実行する。
xx/yyはパッケージ名。例えばこんな感じ。
composer update cakedc/search
これで、不要なパッケージは、composer.lockからも削除され、実ファイル群も削除される。
uninstall command please.
1. まずcomposer.json から不要なパッケージの行を削除。
2. composer update xx/yy を実行する。
xx/yyはパッケージ名。例えばこんな感じ。
composer update cakedc/search
これで、不要なパッケージは、composer.lockからも削除され、実ファイル群も削除される。
2014年4月1日火曜日
[CakPHP]]Warning (512): SplFileInfo::openFile(/path/to/app/tmp/cache/cake_toolbar_cache20dabd4b42c7aea65f12ba6b3ed09c3b): failed to open stream: Permission denied [CORE/Cake/Cache/Engine/FileEngine.php, line 355]
こんな感じのエラーが出たら、とりあえず、
cd app/tmp/cache
chmod 666 cake_toolbar_cache20dabd4b42c7aea65f12ba6b3ed09c3b
をやればエラーは出なくなる。
SplFileInfo::openFile(/app/tmp/cache/persistent/cake_core_cake_console_):failed to open stream:Permission denied in /lib/…/FileEngine.php line 293
ここを参考にした。core.phpをいじることで恒常的に直せそうだけども今回は暫定対処で。
cd app/tmp/cache
chmod 666 cake_toolbar_cache20dabd4b42c7aea65f12ba6b3ed09c3b
をやればエラーは出なくなる。
SplFileInfo::openFile(/app/tmp/cache/persistent/cake_core_cake_console_):failed to open stream:Permission denied in /lib/…/FileEngine.php line 293
ここを参考にした。core.phpをいじることで恒常的に直せそうだけども今回は暫定対処で。
登録:
投稿 (Atom)
