CakePHP Archive
CakePHP1.1.8.3544への移行
既にCakePHP1.1.7.3363で動作しているシステムをCakePHP1.1.8.3544にアップグレードする方法です。
- 念のため既存のソースを全てバックアップ
- 1.1.8.3544のcake/を既存のcake/にコピー
- 1.1.8.3544のapp/webroot/css.php,app/webroot/js/vendors.phpを既存のディレクトリにコピー
フレームワークを変更している場合は別途修正が必要になりますのでご注意を。
ちなみに以前このサイトで公開したパッチは1.1.8.3544でもそのまま使用できます。もしご利用の方は1.1.8.3544にアップグレード後、パッチを当ててください。
- コメント (Close): 0
- Trackbacks: 0
CakePHP1.1.8.3544リリース
CakePHP1.1.8.3544がリリースされています。1.1系では最後のリリースになるようです。1.2系は来年みたいですね。
CakePHP 1.1.8.3544 is the latest release and brings us to the point of some more exciting new changes.
While this release signals the end of the 1.1 series, it also provides the starting point for the next year.CakeForge: CakePHP: File Release Notes and Changelog (2006-09-22)
数多くの修正が行われており、先日のvendors.phpに関する修正も取り込まれているのでアップデートした方が良いでしょう。
ダウンロード:http://cakeforge.org/frs/?group_id=23&release_id=134
# ダウンロードファイル選択後に寄付を呼びかけるページが表示されます。
# 寄付しない場合は「No Thanks」を選択すればダウンロードページへ進めます。
- コメント (Close): 0
- Trackbacks: 0
CakePHP controller共通のモデル、コンポーネント、ヘルパーを設定する
controller共通のモデル、コンポーネント、ヘルパーを設定する方法です。
We all know the problem, there are always Models, Components or Helpers that we need for about 99% of all our actions/views and therefor would fit beautifully in our AppController. The only problem is, as soon as we define them via “var $uses = array(‘…’);” (etc.), we cannot easily add more items in our derived controllers without having to repeat the entire list.
ThinkingPHP and beyond » Dessert #10 – Default Models, Components & Helpers (2006-09-19)
これ私も気になっていた箇所なので、そうそう、といった感じでした。エントリではAppControllerのコンストラクタで$uses,$components,$helpersをマージする方法が紹介されています。
こういう方法もあるかなーと見ていると、上記エントリのコメントでさっくりと突っ込まれました。実はこれControllerクラスのコンストラクタでマージしてくれるようになっているんですね。以下のソースでAppControllerで設定したコンポーネントがTestControllerで使えます。すっきり、すっきり。
[app/app_controller.php]
< ?php class AppController extends Controller { var $components = array('RequestHandler'); } ?>
[app/controllers/test_controller.php]
< ?php class TestController extends AppController { var $name = "Test"; var $components = array('Session'); function index() { // RequestHandlerもSessionも使える if ($this->RequestHandler->isGet()) { $this->Session->destroy(); } } } ?>
- コメント (Close): 0
- Trackbacks: 1
CakePHP vendors.phpにセキュリティホール
cakebakerやCakePHP Users in JapanにもあるようにCakePHPにて任意のファイルが読み込めるセキュリティホールが見つかっています。
問題となるファイルは[app/webroot/js/vendors.php]です。このファイルはvendors/javascript/以下にあるjsファイルを読み込むものなのですが、is_file()やreadfile()がバイナリセーフではないため%00をファイル名に挿入することにより任意のファイルを読めてしまいます。
対応策は以下になります。
- 修正済みファイルを適用する。
- 使用していないならvendors.phpを削除してしまう。
そもそも[app/vendors/javascript]が無い場合はvedors.phpは使用していないはずのですので。(デフォルトでは[app/vendors/javascript])はありません。 - magic_quotes_gpcをOnにする。
文字化けの問題があるので日本語圏ではこれは無いでしょうね。
ただ現時点ではbake.phpで使用するテンプレートが修正されてないため、bake.phpで新規プロジェクトを作るとまた同じ問題が発生してしまいます。その場合は再度対策が必要となるためご注意を。
追記:
bake用テンプレートも修正されました。(Thanks dho!)
あとちょっと気になるのはjsファイルかどうか正規表現の部分です。
if(is_file('../../vendors/javascript/'.$file) && (preg_match('/(\/.+)\\.js/', $file)))
ここは後方一致になるように’/(\/.+)\\.js$/’にしておいた方が良いかと。あとこれは純粋に疑問なのですが\/はなぜ必要なのでしょうか。
まあこのファイル自体使いどころが良く分からなかったりするのですが。:P
- コメント (Close): 0
- Trackbacks: 0
CakePHP 環境に応じてDBの設定を変える
本番環境や開発環境など環境に応じてDBの設定を変える方法です。
1.AppModelを書き換える
withcakeで紹介されている方法です。
AppModelのコンストラクタで切り替えるアイデアは分かりやすくて良いと思います。ちなみに記事のコメントにもあったのですが、記事のコードだとコンストラクタの引数がModelへ渡されませんので、修正版を以下に書いておきます。
[app/app_model.php]
class AppModel extends Model { function __construct($id = false, $table = null, $ds = null) { $this->useDbConfig = $_SERVER['HTTP_HOST'] == 'devserver'?'test':'default'; parent::__construct($id, $table, $ds); } }
2.database.phpを書き換える
NoswaDで紹介されている方法です。
cakebakerでも書かれていますが、database.phpは設定ファイルなので、これにコードを入れるのは若干抵抗を感じます。(まあdatabase.phpがなぜクラスになっているのか?という考えもありますが。)
3.Subversionで切り替える
cakebakerで紹介されている方法です。
I try to avoid to add code to configuration files because those files shouldn’t contain any logic. Instead I use Subversion to manage different configurations. In my repository I have at least two folders for each project: a “trunk” folder where the development happens, and a “live” folder which contains the code (and configurations) for the live application. So if I put something online I just export the content of the “live” folder from the repository, and with it the “live” configuration.
cakebaker » An alternative to “hacking” config files (2006-09-17)
「Subversion使えよ。なんでハックなんかやってるの?」と言ったところでしょうか。:)詳しい実践方法の記述が無いので的外れの可能性大ですが、これだとtrunk/とlive/でコードが別々になるような気がするのですが、どうなんでしょうか。
4.環境変数で切り替える
1.の変形版です。開発環境ではIPが変わる事があるので、環境変数で切り替える方法を考えてみました。これなら実行環境のIPがどうなろうと影響を受けません。
[httpd.conf]
SetEnv CAKE_DB_CONFIG test
[app/app_model.php]
< ?php class AppModel extends Model { function __construct($id = false, $table = null, $ds = null) { $this->useDbConfig = empty($_SERVER['CAKE_DB_CONFIG']) ? 'default' : $_SERVER['CAKE_DB_CONFIG']; parent::__construct($id, $table, $ds); } } ?>
httpd.confで環境変数CAKE_DB_CONFIGを定義しておけば、その値をuseDbConfigに使用し、定義がなければ’default’を使用します。使い方としては本番環境が’default’で、開発環境等の他の環境は’dev’等を定義する形を考えています。
- コメント (Close): 0
- Trackbacks: 5
CakePHP 配列の考え方
モデルやコントローラで値の受け渡しは配列を使います。この配列はちょっとクセがあって$array[モデル名(or テーブル名)][カラム名]という形式になっています。これはちょっと抵抗がありました。1レコードの値を配列に入れるなら$array[カラム名]の方が自然だと思っていたからです。
ところが、ある事に気づいた時から「ああ、なるほど。」としっくりいくようになりました。
さてそれは何かと言うと、なんてことはない、これSQLと一緒なんですね。
select table.column from table;
これが分かってから何だかすっきりしました。
- コメント (Close): 0
- Trackbacks: 0
CakePHP アプリケーションの設定情報をまとめる
Amazonのアクセスキーやメールサーバホスト等、アプリケーション固有の設定情報(パラメータ)を一元的に記述する方法を考えてみました。
1.core.phpに記述する
[app/config/core.php]にはフレームワークが使用するパラメータが記述されています。これに続いてアプリケーションの設定を記述する方法です。シンプルで分かりやすいですが、フレームワーク自体の設定と一緒になってしまうので、混同しやすいかもしれません。
[app/config/core.php]
< ?php #snip /** * application config */ define('MAIL_SMTP', 'mail.example.com'); define('AMAZON_ACCESS_KEY', 'xxxxxxxxxx'); define('SYSTEM_PARAMETER', 'yyy'); ?>
2.アプリケーション用の設定ファイルに記述する
アプリケーション用の設定は[app/config/app.php]に記述してAppControllerで読み込む方法です。これならフレームワークの設定とは切り離せますし、各controllerでは設定ファイルを意識する事なくパラメータを使用できます。
[app/config/app.php]
< ?php define('MAIL_SMTP', 'mail.example.com'); define('AMAZON_ACCESS_KEY', 'xxxxxxxxxx'); define('SYSTEM_PARAMETER', 'yyy'); ?>
[app/app_controller.php]
< ?php #snip config('app'); #snip class AppController extends Controller { } ?>
今回は設定値をPHPの定数で定義する方法を取りました。定数はどこからでも透過的にアクセスできるので扱いが楽ですね。ただ設定値をアプリケーションで変更できないですし、もし開発者以外が設定を触るならiniファイル形式の方が良いかもしれません。いずれこちらの方法も考えてみたいと思います。
- コメント (Close): 0
- Trackbacks: 2
CakePHP Controller小話
9月に入りましたが、まだまだ暑い日が続きますね。アイスコーヒーとエアコンが欠かせません。さてここでbakerの皆さんに涼しくなる小話でも。
CakePHPでは1アクションがcontrollerの1メソッドになっています。アクション名(メソッド名)はリクエストのあったURLから決定されます。つまり外部からcontrollerのメソッドを実行できてしまうわけです。ただフレームワークがアクションメソッドだけをアクションとして実行するようにしてくれれば問題は無いはずです。ではURLで指定されたアクション(メソッド)がアクションメソッドかどうかどのように判断しているのでしょうか。
これが実は通常のメソッドとアクションメソッドとの区別は無いんですね。フレームワークはURLで指定されたアクション(メソッド)を単に呼んでいるだけなのです。つまりcontroller内のメソッドは外から呼び放題なわけです。
ちょっと涼しくなってきましたか?
こりゃいけないって事でアプリケーションのcontrollerではアクションメソッドだけを書きましょう、という話になるのですが、それだけではダメなんです。そう親クラスのControllerには多くのメソッドがあるんですね。それを継承しているんで、当然Controllerクラスのメソッドも呼び放題なわけです。
背中がゾクッとしてきましたね。
さらに付け加えるとURLの指定でメソッドに引数を与えることもできてしまいます。
怖いですねー。ホラーですねー。
で、どうしましょ。という話です。
まず以下に該当するメソッドはアクションとしては実行されません。
- メソッド名が[_](アンダースコア)ではじまるもの
- beforeFilter,beforeRender,afterFilterメソッド
- アクセス制御子がprivateのメソッド(PHP5のみ。これはPHP自身がFatal errorを出す)
これを見るとAppControllerや各controllerでは1.か3.のルールでメソッドを書けば大丈夫なようです。
ただControllerクラスのメソッドで上記のルールに該当しないものはやはり呼ばれてしまいます。とりあえずの実害は(おそらく)無いのでしょうけど、根本的に任意のメソッドを外部から呼ばれてしまうのは気持ち悪いです。そこでまたパッチ[cakephp_action_method.patch]を作りました。
このパッチではaction_~ではじまるメソッドのみをアクションとして実行します。アクションのメソッド名は[action_ + アクション名]になります。例えば/post/indexに対応するメソッド名は[action_index]になります。(ビューファイル名は従来とおりアクション名のみで良いです。)
[app/controllers/post_controller.php] < ?php class PostController extends AppController { function action_index() { // indexアクションとして呼ばれる } function other_method() { // これはアクションとして外部から呼ばれない } } ?>
これで外部からはcontrollerのaction_~以外のメソッドは呼べなくなります。精神衛生上はこの方が良いかと。無保証ですがよろしければどうぞ。
- コメント (Close): 6
- Trackbacks: 1
CakePHP URLマッピング修正パッチ
CakePHP 管理者用アクションに書いた/admin以下をApacheのBasic認証やIP制限でアクセス制限する方法ですが、CakePHP1.1.7.3363ではApache側のアクセス制限を回避されてしまう可能性があります。
この現象はURLのQUERY_STRINGにurl=を指定した場合に発生します。具体的には
http://www.example.com/post/index?url=/admin/user/index
でアクセスするとPostController#index()が呼ばれるのではなく、UserController#admin_index()が呼ばれてしまいます。
Apache側の設定(LocationMatch等)を上手く使う手もあるのですが、そもそもコントローラとアクションが上書きされてしまう事自体が問題だと思うので、修正パッチを書きました。気になる方はどうぞ。
- コメント (Close): 1
- Trackbacks: 1
CakePHPでDBアクセスなしのModelを作る
CakePHPのmodelはDBのテーブルと1対1になる事が想定されています。ただシステムを構築する際はこのような単純なmodelだけでは使い勝手が悪い場合があります。そこでDBアクセス無しのmodelの作成方法を模索してみました。
フレームワークのソースを見たところmodelの$useTableにfalseをいれておけば良いようです。
[app/models/no_db.php]
<?php class NoDb extends AppModel { $useTable = false; } ?>
では、modelなしのcontrollerはというと・・・フレームワークを見る限りでは方法は無さそうですね。ただcontrollerの$nameでmodel名を指定する事ができるので、これにダミーのmodelを指定すれば、modelを新たに作らずにcontroller・ビューファイルを追加する事が可能です。
[app/controllers/no_my_model_controller.php]
<?php class NoMyModelController extends AppController { var $name = 'NoDb'; function index() { $this->viewPath = 'no_my_model'; // ビューファイルディレクトリを指定 } } ?>
index()内のviewPathの設定を行わないと$nameの値でビューファイルディレクトリ名が決定されてしまうので注意が必要です。(ビューファイルもmodel同様に共通で良ければこの行は必要ありません。)
修正:2006/09/15
modelなしのcontrollerも作れますね。controllerの$usesをarray()かnullにすれば良いようです。
class MyController extends AppController { // var $uses = null; works too var $uses = array(); function index() { } }
- コメント (Close): 0
- Trackbacks: 0
- 検索
- フィード
- メタ情報