スタッフブログ
satoです。
今回は、以前紹介したLaunchyで、CHMヘルプファイルをキーワード付きで簡単に呼び出せるようにしたいと思います。
とは言っても非常に簡単で、saitou155・プログラム技術のページで公開されているhhh.exeを使うだけです。
通常のCHMヘルプファイルは、hh.exeというプログラムが読み込んで表示するのですが、hh.exeはコマンドラインオプションでキーワードを渡して開く機能がありません。
そこで、hhh.exeを代わりに使用します。
設定自体は簡単で、Runnerプラグインで、
Name:呼び出す時に使う名前
Program:hhh.exeのパス
Arguments:[CHMファイルのパス] $$
と指定しておけば、「[Name][Tab][キーワード]」と入力するとCHMファイルの指定キーワード部分が開きます。
ただしCHMファイルによって挙動がまちまちで、キーワード検索に文字が入っているだけのものもあれば、該当ページまで自動的に開くものもあるようです。原因は不明です。
以前紹介した通り、CHMファイルは非常に便利だと思うのですが、開くのが面倒という難点がありました。
これにより、多少難点があるものの、どの状況でもキーワード検索が簡単に呼び出せるようになるので、CHMファイルを更に有効活用できるようになります。是非お試しください。
今回は、以前紹介したLaunchyで、CHMヘルプファイルをキーワード付きで簡単に呼び出せるようにしたいと思います。
とは言っても非常に簡単で、saitou155・プログラム技術のページで公開されているhhh.exeを使うだけです。
通常のCHMヘルプファイルは、hh.exeというプログラムが読み込んで表示するのですが、hh.exeはコマンドラインオプションでキーワードを渡して開く機能がありません。
そこで、hhh.exeを代わりに使用します。
設定自体は簡単で、Runnerプラグインで、
Name:呼び出す時に使う名前
Program:hhh.exeのパス
Arguments:[CHMファイルのパス] $$
と指定しておけば、「[Name][Tab][キーワード]」と入力するとCHMファイルの指定キーワード部分が開きます。
ただしCHMファイルによって挙動がまちまちで、キーワード検索に文字が入っているだけのものもあれば、該当ページまで自動的に開くものもあるようです。原因は不明です。
以前紹介した通り、CHMファイルは非常に便利だと思うのですが、開くのが面倒という難点がありました。
これにより、多少難点があるものの、どの状況でもキーワード検索が簡単に呼び出せるようになるので、CHMファイルを更に有効活用できるようになります。是非お試しください。
satoです。
CakePHPの1.1→1.2は、一部大きな修正があります。そのまま使おうとすると、思った通りに動作しない可能性があります。
今回は大きな変更が加えられているSecurityコンポーネントについて説明します。
Securityコンポーネントは、1.1では大きく2つの機能があります。
・CSRF対策
・POSTメソッド制限
※今回の調査に関して、CakePHP1.1の通常パッケージのダウンロード先がわからなかったため、nightlyを使用しています。
1.1では、controllerのbeforeFilter内で、
のようにすると、addアクションでのみトークンチェックが入ります。
また、$this->Security->requirePost('add');のようにすると、addはPOSTメソッドでしかアクセスできなくなります。
1.2では、機能自体が大幅に増えています。
1.1の機能の他に
・BASIC/DIGEST認証
・POST以外のメソッド制限(GET/PUT/DELETE)
・SSLチェック
といったものが増えています。
しかし、CSRF対策のコードが、1.1と1.2で別物になっています。
1.1は
・startup内で、requireAuthに現在のアクション名が入っていたら、トークンチェックを行う
というものでしたが、1.2では、
・requireAuthに現在のアクション名が含まれる場合、allowedControllersとallowedActionsをチェックする(含まれない場合は特に何もチェックしない)
・controllerにrequested==1というパラメータが入っているか、validatePost==trueでない限り、POSTリクエスト時に_validatePostでトークンのチェックを常に行う
という、不可解な挙動をします。
つまり、requireAuthに何が入っていても、Securityコンポーネントを組み込んだ時点で全ての画面にトークンチェックが入ることになります。
ドキュメントを見る限りだと、1.2でもrequireAuthを見てトークンチェックを行うような感じではあるのですが、どう解釈していいのかわからないところです。
現状としては、Securityコンポーネント自体を使わず、独自でCSRF対策を用意するのが無難だと思います。
この他にも1.2での変更点は多いので、1.2をダウンロードして1.1の解説サイトを見て困らないように注意しましょう。
CakePHPの1.1→1.2は、一部大きな修正があります。そのまま使おうとすると、思った通りに動作しない可能性があります。
今回は大きな変更が加えられているSecurityコンポーネントについて説明します。
Securityコンポーネントは、1.1では大きく2つの機能があります。
・CSRF対策
・POSTメソッド制限
※今回の調査に関して、CakePHP1.1の通常パッケージのダウンロード先がわからなかったため、nightlyを使用しています。
1.1では、controllerのbeforeFilter内で、
function beforeFilter() {
$this->Security->requireAuth('add');
}
のようにすると、addアクションでのみトークンチェックが入ります。
また、$this->Security->requirePost('add');のようにすると、addはPOSTメソッドでしかアクセスできなくなります。
1.2では、機能自体が大幅に増えています。
1.1の機能の他に
・BASIC/DIGEST認証
・POST以外のメソッド制限(GET/PUT/DELETE)
・SSLチェック
といったものが増えています。
しかし、CSRF対策のコードが、1.1と1.2で別物になっています。
1.1は
・startup内で、requireAuthに現在のアクション名が入っていたら、トークンチェックを行う
というものでしたが、1.2では、
・requireAuthに現在のアクション名が含まれる場合、allowedControllersとallowedActionsをチェックする(含まれない場合は特に何もチェックしない)
・controllerにrequested==1というパラメータが入っているか、validatePost==trueでない限り、POSTリクエスト時に_validatePostでトークンのチェックを常に行う
という、不可解な挙動をします。
つまり、requireAuthに何が入っていても、Securityコンポーネントを組み込んだ時点で全ての画面にトークンチェックが入ることになります。
ドキュメントを見る限りだと、1.2でもrequireAuthを見てトークンチェックを行うような感じではあるのですが、どう解釈していいのかわからないところです。
現状としては、Securityコンポーネント自体を使わず、独自でCSRF対策を用意するのが無難だと思います。
この他にも1.2での変更点は多いので、1.2をダウンロードして1.1の解説サイトを見て困らないように注意しましょう。
satoです。
先日、自宅のPCを総入れ替えしたのですが、その際にWindows Vistaのx64(64bit)版を導入しました。
日本での普及率はまだまだ低いx64Windowsなのですが、ソニーのVAIOの次期モデルでは全面的にx64版を採用するなど、着々と普及が始まっています。
しかし未だにWindowsXP(32bit)以外使いたくないという偏見が広まっています。
現状では「Vistaでしか動かないキラーアプリ」的なものが存在しないので、それなら面倒なUACを使うより全部動くXPを使う、というのは正しいのですが、サポートの問題などもありますので、今からXPを購入するというのは控えるべきだと思います。
また、64bitが普及しないと、メモリ空間の限界等の問題で、ハードウェアを有効利用できないという問題があります。
というところまではx64を使おうとしている方ならご存じだとは思うのですが、実際「ドライバがないよね」「あのソフトは動くのかな…」という点で避けている部分は大きいと思います。
しかし探してみると、64bitドライバは思っているより多いことがわかります。ソフトも64bit版が出ていなくても普通に動くことが多いです。
というわけでx64導入の注意点を洗い出してみようと思います。
・TVチューナー/キャプチャー系はほぼ買い換えが必要
これはx64というよりVistaの問題でもあるのですが、VistaではTVチューナーの動作が厳しくなっております。
また、公式にサポートされているものでも、ほとんどのものはTVチューナーを起動するとAeroが無効になります。
・古いものは買い換える
使えるからと言って古いものを無理に使おうとせず、同種の新しいものがあればそちらを使ったほうがいいです。
ほとんどのデバイスは、新しいものであれば正常に動作します。有名メーカーのものであれば64bitドライバが大体用意されています。
・管理者権限に注意する
これもVista自体の問題ですが、VistaはUACが搭載されているため、権限を無視してファイルアクセスするフリーソフト等は動作しないことが多いです。
この場合は、exeファイルのショートカットを作成し(既にあればそのまま)、そのショートカットファイルのプロパティで、「詳細設定」で「管理者として実行」にチェックを入れておけば、毎回管理者権限で実行されます。
管理者確認のダイアログが毎回出るのが鬱陶しい場合は、Norton UAC Toolを使用することで、アプリケーション毎に2回目の警告を無効化することができます。UACを根本的に切るのは避けましょう。
x64版Vistaは、32bitプロセスと64bitプロセスが混在できるようになっているため、32bitアプリでもほとんどの場合で正常に動作するようになっております。
挙動が若干おかしい、程度ならいくつかありましたが、全く動作しないというのは今のところゲーム以外では遭遇していません。
挙動がおかしいものとしては、例えば以前紹介したLaunchyでは、たまにキー入力が効かなくなることがあります。(32bitVistaでは正常動作)
ちなみに速度に関してもよくVistaは遅いと言われますが、SuperFetchやAeroの3Dアクセラレーションにより、Vista対応スペックを十分に満たしているPCであればXPより快適になるケースも少なくありません。
低スペックPCで使うということでなければ安易に無効化しないほうがいいです。(ただしバッテリー消費を減らしたいとかの理由であれば別)
もちろん、高速と言われているWindows 7まで待つのもいいと思います。
---
ところで、先日から、XOOPS CubeでYiiを使うモジュールをこっそり公開しております。
サポートはできませんが、興味のある方は使ってみてください。
先日、自宅のPCを総入れ替えしたのですが、その際にWindows Vistaのx64(64bit)版を導入しました。
日本での普及率はまだまだ低いx64Windowsなのですが、ソニーのVAIOの次期モデルでは全面的にx64版を採用するなど、着々と普及が始まっています。
しかし未だにWindowsXP(32bit)以外使いたくないという偏見が広まっています。
現状では「Vistaでしか動かないキラーアプリ」的なものが存在しないので、それなら面倒なUACを使うより全部動くXPを使う、というのは正しいのですが、サポートの問題などもありますので、今からXPを購入するというのは控えるべきだと思います。
また、64bitが普及しないと、メモリ空間の限界等の問題で、ハードウェアを有効利用できないという問題があります。
というところまではx64を使おうとしている方ならご存じだとは思うのですが、実際「ドライバがないよね」「あのソフトは動くのかな…」という点で避けている部分は大きいと思います。
しかし探してみると、64bitドライバは思っているより多いことがわかります。ソフトも64bit版が出ていなくても普通に動くことが多いです。
というわけでx64導入の注意点を洗い出してみようと思います。
・TVチューナー/キャプチャー系はほぼ買い換えが必要
これはx64というよりVistaの問題でもあるのですが、VistaではTVチューナーの動作が厳しくなっております。
また、公式にサポートされているものでも、ほとんどのものはTVチューナーを起動するとAeroが無効になります。
・古いものは買い換える
使えるからと言って古いものを無理に使おうとせず、同種の新しいものがあればそちらを使ったほうがいいです。
ほとんどのデバイスは、新しいものであれば正常に動作します。有名メーカーのものであれば64bitドライバが大体用意されています。
・管理者権限に注意する
これもVista自体の問題ですが、VistaはUACが搭載されているため、権限を無視してファイルアクセスするフリーソフト等は動作しないことが多いです。
この場合は、exeファイルのショートカットを作成し(既にあればそのまま)、そのショートカットファイルのプロパティで、「詳細設定」で「管理者として実行」にチェックを入れておけば、毎回管理者権限で実行されます。
管理者確認のダイアログが毎回出るのが鬱陶しい場合は、Norton UAC Toolを使用することで、アプリケーション毎に2回目の警告を無効化することができます。UACを根本的に切るのは避けましょう。
x64版Vistaは、32bitプロセスと64bitプロセスが混在できるようになっているため、32bitアプリでもほとんどの場合で正常に動作するようになっております。
挙動が若干おかしい、程度ならいくつかありましたが、全く動作しないというのは今のところゲーム以外では遭遇していません。
挙動がおかしいものとしては、例えば以前紹介したLaunchyでは、たまにキー入力が効かなくなることがあります。(32bitVistaでは正常動作)
ちなみに速度に関してもよくVistaは遅いと言われますが、SuperFetchやAeroの3Dアクセラレーションにより、Vista対応スペックを十分に満たしているPCであればXPより快適になるケースも少なくありません。
低スペックPCで使うということでなければ安易に無効化しないほうがいいです。(ただしバッテリー消費を減らしたいとかの理由であれば別)
もちろん、高速と言われているWindows 7まで待つのもいいと思います。
---
ところで、先日から、XOOPS CubeでYiiを使うモジュールをこっそり公開しております。
サポートはできませんが、興味のある方は使ってみてください。
2/14は札幌のLOCAL DEVELOPER DAY '09 /Winterに参加する予定のsatoです。
北海道近辺の技術者の方は是非参加してみてください。
今日は以前発見したIE(6/7)の謎の挙動に関して紹介したいと思います。バグだと思うのですが…。
テストページを用意しました。
まずこちらをIE以外のブラウザでご覧下さい。
[テストページ]
普通にスクロールバーが表示されると思います。
次に、IEで表示させると、スクロールバーが出ないと思います。
しかし、インラインフレームの領域をクリック、あるいは画面内のどこかをクリックしてからインラインフレームにカーソルを当てると、突然スクロールバーが出てきます。
使用したソースは以下になります。
index.html
scroll.html
どうやら「インラインフレームの幅が20px以下で、インラインフレーム中にスクロールバーが表示される場合」に正常に描画できないようです。
20pxはOSのスクロールバーの設定次第で変わるかもしれません。
通常このようなHTMLを書くことはないと思いますが、もし書くことがあれば注意してください。
北海道近辺の技術者の方は是非参加してみてください。
今日は以前発見したIE(6/7)の謎の挙動に関して紹介したいと思います。バグだと思うのですが…。
テストページを用意しました。
まずこちらをIE以外のブラウザでご覧下さい。
[テストページ]
普通にスクロールバーが表示されると思います。
次に、IEで表示させると、スクロールバーが出ないと思います。
しかし、インラインフレームの領域をクリック、あるいは画面内のどこかをクリックしてからインラインフレームにカーソルを当てると、突然スクロールバーが出てきます。
使用したソースは以下になります。
index.html
<html>
<body>
<iframe style="width:20px;" src="scroll.html"></iframe>
</body>
</html>
scroll.html
<html>
<body>
<div style="height: 10000px"></div>
</body>
</html>
どうやら「インラインフレームの幅が20px以下で、インラインフレーム中にスクロールバーが表示される場合」に正常に描画できないようです。
20pxはOSのスクロールバーの設定次第で変わるかもしれません。
通常このようなHTMLを書くことはないと思いますが、もし書くことがあれば注意してください。
satoです。
JavaScriptのライブラリでお馴染みのものにPrototype(prototype.js)があります。
このライブラリは、早い段階からJavaScriptでクラス機構を実現するための仕組みが用意されていたのですが、あまり使い勝手がいいと言えるものではありませんでした。
一昨年くらいに1.6がリリースされて、クラス作成周りが一新されたのですが、あまり情報がない(というか、あるのですが古い情報が優先して検索される)ので、ここでも書いておこうと思います。
■クラス作成
・1.5以前
・1.6
Class.createの中に直接書けるようになりました。ちなみに1.5以前の書き方でも通るようになっていますが、この後の継承などで問題が出ると思うので、1.6の書き方を使うようにしましょう。
■継承
・1.5以前
・1.6
Object.extendを使わなくなったのが大きな違いです。
そもそもObject.extendの実装を見ると、
のように、プロパティをコピーしているだけで、継承と呼ぶには厳しい実装でした。どちらかといえばmixinに近い実装だと思います。
1.6の実装になって何が嬉しいかと言うと、
・書き方がわかりやすい
Object.extendを複数回呼ぶ必要もありませんし、明示的にprototypeを指定する必要もなくなりました。
・親クラスのメンバを呼べるようになった
恐らくこれが一番大きいです。
1.5では、
のような強引な手法を採るしかありませんでしたが、1.6では、
のように、第一引数を$superという名前にすると、そこに親クラスのメソッドが入るようになりました。
ちなみにこの場合、getNameに引数を渡して受け取る場合、第二引数以降に割り当てられます。
みたいな感じです。
■まとめ
そもそもクラスとか定義するのはJavaScriptっぽくない感じはするのですが、単純に慣れているというのと、可読性が向上するという意味で積極的に使うようにしています。
最近はjQuery派とフルスクラッチ派が強い印象がありますが、prototype.jsは基本機能が整っていて、今でも十分実用的に使えるライブラリだと思います。
JavaScriptのライブラリでお馴染みのものにPrototype(prototype.js)があります。
このライブラリは、早い段階からJavaScriptでクラス機構を実現するための仕組みが用意されていたのですが、あまり使い勝手がいいと言えるものではありませんでした。
一昨年くらいに1.6がリリースされて、クラス作成周りが一新されたのですが、あまり情報がない(というか、あるのですが古い情報が優先して検索される)ので、ここでも書いておこうと思います。
■クラス作成
・1.5以前
var Animal = Class.create();
Animal.prototype = {
initialize: function() {
this.name = 'Animal';
},
getName: function() {
return this.name;
}
};
alert(new Animal().getName()); // 'Animal'
・1.6
var Animal = Class.create({
initialize: function() {
this.name = 'Animal';
},
getName: function() {
return this.name;
}
});
alert(new Animal().getName()); // 'Animal'
Class.createの中に直接書けるようになりました。ちなみに1.5以前の書き方でも通るようになっていますが、この後の継承などで問題が出ると思うので、1.6の書き方を使うようにしましょう。
■継承
・1.5以前
var Animal = Class.create();
Animal.prototype = {
initialize: function() {
this.name = 'Animal';
},
getName: function() {
return this.name;
}
};
var Cat = Class.create();
Object.extend(Cat.prototype, Animal.prototype);
Object.extend(Cat.prototype, {
initialize: function() {
this.name = 'Cat';
}
});
alert(new Animal().getName()); // 'Animal'
alert(new Cat().getName()); // 'Cat'
・1.6
var Animal = Class.create({
initialize: function() {
this.name = 'Animal';
},
getName: function() {
return this.name;
}
});
var Cat = Class.create(Animal, {
initialize: function() {
this.name = 'Cat';
}
});
alert(new Animal().getName()); // 'Animal'
alert(new Cat().getName()); // 'Cat'
Object.extendを使わなくなったのが大きな違いです。
そもそもObject.extendの実装を見ると、
Object.extend = function(destination, source) {
for (var property in source) {
destination[property] = source[property];
}
return destination;
}
のように、プロパティをコピーしているだけで、継承と呼ぶには厳しい実装でした。どちらかといえばmixinに近い実装だと思います。
1.6の実装になって何が嬉しいかと言うと、
・書き方がわかりやすい
Object.extendを複数回呼ぶ必要もありませんし、明示的にprototypeを指定する必要もなくなりました。
・親クラスのメンバを呼べるようになった
恐らくこれが一番大きいです。
1.5では、
var Cat = Class.create();
Object.extend(Cat.prototype, Animal.prototype);
Object.extend(Cat.prototype, {
initialize: function() {
this.name = 'Cat';
},
getName: function() {
return (Animal.prototype.getName.bind(this))() + 'だよ';
}
});
alert(new Animal().getName()); // 'Animal'
alert(new Cat().getName()); // 'Catだよ'
のような強引な手法を採るしかありませんでしたが、1.6では、
var Cat = Class.create(Animal, {
initialize: function() {
this.name = 'Cat';
},
getName: function($super) {
return $super() + 'だよ';
}
});
alert(new Animal().getName()); // 'Animal'
alert(new Cat().getName()); // 'Catだよ'
のように、第一引数を$superという名前にすると、そこに親クラスのメソッドが入るようになりました。
ちなみにこの場合、getNameに引数を渡して受け取る場合、第二引数以降に割り当てられます。
getName('hoge') → getName: function($super, hoge) {
みたいな感じです。
■まとめ
そもそもクラスとか定義するのはJavaScriptっぽくない感じはするのですが、単純に慣れているというのと、可読性が向上するという意味で積極的に使うようにしています。
最近はjQuery派とフルスクラッチ派が強い印象がありますが、prototype.jsは基本機能が整っていて、今でも十分実用的に使えるライブラリだと思います。
satoです。
今回は、前回に引き続き、Flashを作ってみました。
[こちらからご覧下さい]
クリックすると何か出ます。それだけです。時間がなかったのでしょぼくて申し訳ないです。
今回はBox2DFlashAS3を使用しています。
前回使用したAPEより高機能で、描画ロジックが分離されているため、PaperVision3D等と組み合わせることも可能なのですが、資料が少なく、情報を調べるのが若干面倒です。
基本的には、gihyo.jp様の連載を見ながら進めるのが一番覚えやすいと思います。
ただし、現行バージョンとは若干違う部分もあるようなので、更に詳しくはBox2Dのマニュアル(日本語訳)やクラスリファレンスを参照するといいと思います。Box2DFlashAS3自体の公式のドキュメントはほとんど存在しないようです。(Box2DFlashAS3はBox2DをAS3に移植したものです)
Box2DFlashAS3で作られたものは、引越し奉行等が有名だと思います。
アイデア次第でいろいろ作れると思うので、是非試してみてください。
今回は、前回に引き続き、Flashを作ってみました。
[こちらからご覧下さい]
クリックすると何か出ます。それだけです。時間がなかったのでしょぼくて申し訳ないです。
今回はBox2DFlashAS3を使用しています。
前回使用したAPEより高機能で、描画ロジックが分離されているため、PaperVision3D等と組み合わせることも可能なのですが、資料が少なく、情報を調べるのが若干面倒です。
基本的には、gihyo.jp様の連載を見ながら進めるのが一番覚えやすいと思います。
ただし、現行バージョンとは若干違う部分もあるようなので、更に詳しくはBox2Dのマニュアル(日本語訳)やクラスリファレンスを参照するといいと思います。Box2DFlashAS3自体の公式のドキュメントはほとんど存在しないようです。(Box2DFlashAS3はBox2DをAS3に移植したものです)
Box2DFlashAS3で作られたものは、引越し奉行等が有名だと思います。
アイデア次第でいろいろ作れると思うので、是非試してみてください。
今年もクリスマスは一人で過ごす予定のsatoです。
今日は12/24ということで、Flashで雪を降らせてみました。画面をクリックすると雪らしきものが降ります。
[こちらからご覧下さい]
全然それっぽく見えないかもしれませんが、これはAPEという物理演算ライブラリを使用しています。
今回は短時間で作ったためにやっつけな出来になっていますが、本来はもう少し凝ったことができるようになっています。
機能自体はそんなに多くないので、比較的簡単に利用できると思います。
物理演算なので、単に球体(雪)が落下しているだけではなく、面に対して跳ね返ったり積もったりしているのがわかると思います。
ActionScript用の物理演算ライブラリには他にFisix Engine等があるのですが、Fisix Engineは今回はライセンスの関係で見送りました。ただしこちらのほうが高機能なので、興味のある方は利用してみてください。
それでは、良いクリスマスをお過ごし下さい。
今日は12/24ということで、Flashで雪を降らせてみました。画面をクリックすると雪らしきものが降ります。
[こちらからご覧下さい]
全然それっぽく見えないかもしれませんが、これはAPEという物理演算ライブラリを使用しています。
今回は短時間で作ったためにやっつけな出来になっていますが、本来はもう少し凝ったことができるようになっています。
機能自体はそんなに多くないので、比較的簡単に利用できると思います。
物理演算なので、単に球体(雪)が落下しているだけではなく、面に対して跳ね返ったり積もったりしているのがわかると思います。
ActionScript用の物理演算ライブラリには他にFisix Engine等があるのですが、Fisix Engineは今回はライセンスの関係で見送りました。ただしこちらのほうが高機能なので、興味のある方は利用してみてください。
それでは、良いクリスマスをお過ごし下さい。
satoです。
今日は国産PHP5フレームワークのSabelを使ってみようと思います。
Sabelはチュートリアルが充実しているので簡単に使えると思います。
今回は1.1.2を使ってみようと思います。
■インストール
まずはインストールマニュアルの通りにインストールします。
Windows系でのインストール方法も書かれているので、Windowsで開発している方も簡単に利用できると思います。
Sabelでは、sabelコマンドでファイルの生成などを行います。
PHPでデフォルトタイムゾーンを設定していない場合Strict Standards警告が出るので、php.iniに設定をします。
■データベース
まずはconfig/Database.phpを編集します。
ENVIRONMENTという定数で分岐していますが、これはそれぞれ
・PRODUCTION(リリース版)
・TEST(テスト時に使う用)
・DEVELOPMENT(開発版)
の3種類を設定することができます。今回は試してみるだけなのでDEVELOPMENTのみ設定します。
packageの項目に使用するDBを指定します。今回はMySQLを使用します。
データベースを設定したら、次はテーブルを作成します。
Sabelでは、SQLを書かなくても、PHPコードのみでテーブルを作成することができます。このPHPコードが書かれたファイルを「マイグレーションファイル」と呼びます。
マイグレーションファイルは通常、migration/default/に設置します。
ファイル名に規則があり、
バージョン番号は今回は最初なので1です。モデル名は、小文字にしたものがテーブル名になります。コマンドはテーブルを作成するので「create」です。
今回はPostというモデルを作ってみましょう。ファイル名は「1_Post_create.php」になります。
ファイルを作ったら、実行します。sabelコマンドではなくsakleコマンドを使います。
sbl_versionは、テーブルのバージョン管理に使われているものだと思われます。
テーブルを作成したら、対応するモデルを作成します。
■書き込み
scaffoldが見あたらないので、お試しでも真面目に書き込み画面を作ります。
app/index/controllers/Post.php
■まとめ
斜め読みしただけなので、Sabelの特徴を全く生かしていないですが、雰囲気だけでもわかったと思います。
Sabelはアノテーションとかフロー制御とかが特徴的なので、興味のある方は使ってみてください。
今日は国産PHP5フレームワークのSabelを使ってみようと思います。
Sabelはチュートリアルが充実しているので簡単に使えると思います。
今回は1.1.2を使ってみようと思います。
■インストール
まずはインストールマニュアルの通りにインストールします。
Windows系でのインストール方法も書かれているので、Windowsで開発している方も簡単に利用できると思います。
Sabelでは、sabelコマンドでファイルの生成などを行います。
sabel -l jaでプロジェクトをカレントディレクトリに生成します。
PHPでデフォルトタイムゾーンを設定していない場合Strict Standards警告が出るので、php.iniに設定をします。
[Date] ; Defines the default timezone used by the date functions date.timezone = "Asia/Tokyo"
■データベース
まずはconfig/Database.phpを編集します。
ENVIRONMENTという定数で分岐していますが、これはそれぞれ
・PRODUCTION(リリース版)
・TEST(テスト時に使う用)
・DEVELOPMENT(開発版)
の3種類を設定することができます。今回は試してみるだけなのでDEVELOPMENTのみ設定します。
packageの項目に使用するDBを指定します。今回はMySQLを使用します。
... case DEVELOPMENT: $params = array("default" => array( "package" => "sabel.db.mysql", "host" => "localhost", "database" => "sabeltest", "user" => "sabeluser", "password" => "sabelpass") ); break; ...複数のDBを設定し、状況に応じてそれぞれを利用することもできるようです。マスタ/スレーブ構成などにも対応できそうです。
データベースを設定したら、次はテーブルを作成します。
Sabelでは、SQLを書かなくても、PHPコードのみでテーブルを作成することができます。このPHPコードが書かれたファイルを「マイグレーションファイル」と呼びます。
マイグレーションファイルは通常、migration/default/に設置します。
ファイル名に規則があり、
{バージョン番号}_{モデル名}_{コマンド}.phpという形式でファイル名を付ける必要があります。
バージョン番号は今回は最初なので1です。モデル名は、小文字にしたものがテーブル名になります。コマンドはテーブルを作成するので「create」です。
今回はPostというモデルを作ってみましょう。ファイル名は「1_Post_create.php」になります。
<?php $create->column("id")->type(_INT) ->primary(true) ->increment(true); $create->column("title")->type(_STRING) ->length(256) ->nullable(false); $create->column("body")->type(_TEXT) ->nullable(false); $create->column("created")->type(_DATETIME) ->nullable(false);
ファイルを作ったら、実行します。sabelコマンドではなくsakleコマンドを使います。
sakle Migration development head
sabeluser@localhost[sabeltest]> show tables; +---------------------+ | Tables_in_sabeltest | +---------------------+ | post | | sbl_version | +---------------------+ 2 rows in set (0.00 sec)テーブルが作成されているのがわかると思います。
sbl_versionは、テーブルのバージョン管理に使われているものだと思われます。
テーブルを作成したら、対応するモデルを作成します。
sakle Generator model Post
■書き込み
scaffoldが見あたらないので、お試しでも真面目に書き込み画面を作ります。
app/index/controllers/Post.php
<?php class Index_Controllers_Post extends Sabel_Controller_Page { public function show() { $paginate = new Paginate("Post"); $paginate->setDefaultOrder("created", "desc"); $this-%gt;paginate = $paginate->build(10, $this->request->fetchGetValues()); } public function doPost() { $title = $this->request->fetchPostValue("title"); $body = $this->request->fetchPostValue("body"); $post = new Post(); $post->title = $title; $post->body = $body; $post->created = date('Y-m-d H:i:s'); $post->post(); $this->redirect->to("c: post, a: show"); } }app/index/views/post/show.tpl
<h1>Post</h1> <form action="<?php echo uri("a: doPost") ?>" method="post"> <div>title:<input type="text" name="title" /></div> <div><textarea name="body" rows="5" cols="50"></textarea></div> <div><input type="submit" value="Post" /></div> </form> <hr /> <?php if ($paginate->results): ?> <?php foreach($paginate->results as $post): ?> <div> <h2><?php echo htmlspecialchars($post->title) ?></h2> <div><?php echo nl2br(htmlspecialchars($post->body)) ?></div> </div> <?php endforeach ?> <?php endif ?>これで、 http:// 〜/public/index.php/post/show をブラウザで開くと、画面が表示されます。
■まとめ
斜め読みしただけなので、Sabelの特徴を全く生かしていないですが、雰囲気だけでもわかったと思います。
Sabelはアノテーションとかフロー制御とかが特徴的なので、興味のある方は使ってみてください。
satoです。
今回は普段あまり使われないと思うMySQLのストアドプロシージャについて解説したいと思います。
MySQL5.0以降ではストアドプロシージャが使えるようになっています。
通常MySQLでストアドを使うことはないとは思いますが、一連の、CREATE TABLE等とセットでDB処理を書く時などは便利です。
ストアドプロシージャは各RDBMSで独自に実装していることが多いのですが、MySQLは標準SQL準拠で実装されており、それなりに汎用性があるものになっています。とは言っても、PL/SQLとは違うので、どこで汎用的かと言われると難しいです。
PL/SQLとは違いがありますが、大枠としては似ている部分は多いと思います。
■ストアドプロシージャの作成
ストアドプロシージャの作成にはCREATE PROCEDURE命令を使います。
DELIMITER命令は、文の区切り文字(デリミタ)を変更します。
わかりづらいのですが、CREATE PROCEDURE命令は、「CREATE PROCEDURE」から「END;//」までが1つの文になり、その中で実行する命令を書くので、例えば、
と、DELIMITER無しにすると、「CREATE PROCEDURE」が「VALUES(f);」で終了してしまい、エラーになってしまいます。これを回避するために一時的にデリミタを//にしています。
これで定義した後に、
とすると、INSERT INTOが実行されるのがわかると思います。
■ストアドプロシージャの削除
削除にはDROP PROCEDURE文を使います。DROP TABLE等と同様に、IF EXISTSを付けることができるので、CREATEの前に書いておくと便利かと思われます。
■ストアドファンクション
戻り値が無いものをプロシージャと呼ぶのに対し、戻り値があるものはファンクションと呼びます。
基本的にはプロシージャと同様ですが、いくつか違う点があります。
・引数にinが不要
プロシージャの引数の先頭のinは、「この値は入力値です」というのを指示するためのもので、プロシージャの場合はoutという指定もできます。これはPHPで言うところのリファレンス渡しに近いものになります。
ファンクションの場合はRETURNで戻り値を指定するので不要です。
・戻り値の型の指定
CREATE FUNCTIONの引数リストの後に、「RETURNS int」というのがあります。ここで戻り値の型を指定します。(この場合はint)
・DETERMINISTIC
これを付けないで定義しようとすると、
入力値が同じ場合に出力値が同じ場合はDETERMINISTIC、そうでない場合はNOT DETERMINISTICを指定します。バイナリログの記録に関わるようです。
ファンクションはSELECTで呼び出します。
■変数の定義
内部で使う変数の定義にはDECLARE文を使います。
DECLARE文は全てBEGINの直後に書く必要があります。ルーチンの途中に書くことはできません。
のようなのはエラーになります。
変数に値を代入するにはSET文を使います。
■カーソル
ストアドでよく使う処理として、「SELECTの結果を1行毎に何か処理したい」ということだと思います。PHPのforeach的なものです。
これを実現するにはカーソルというものを使います。
カーソルは、SELECTの戻り値のポインタ的なもので、cursor型として定義します。
「DECLARE cr1 cursor FOR」の後に、そのカーソルで呼び出したいSQLを記述します。
「DECLARE continue handler FOR not found SET eod = 1;」は、カーソル呼び出しの際に、データが存在しなくなったら変数eodに1をセットするというhandlerを定義します。これでSELECTが終了したかどうかを判定します。
カーソルのDECLAREは通常変数のDECLAREの後に定義する必要があります。
のようにしてしまうと、
というエラーになります。
後はカーソルをOPENし、FETCHで値を取得するとINTOで指定した変数に代入され、それを処理します。
これを実行すると、
cが反映されているのがわかると思います。
その他、詳しくはMySQLのリファレンスマニュアルを参照してください。
今回は普段あまり使われないと思うMySQLのストアドプロシージャについて解説したいと思います。
MySQL5.0以降ではストアドプロシージャが使えるようになっています。
通常MySQLでストアドを使うことはないとは思いますが、一連の、CREATE TABLE等とセットでDB処理を書く時などは便利です。
ストアドプロシージャは各RDBMSで独自に実装していることが多いのですが、MySQLは標準SQL準拠で実装されており、それなりに汎用性があるものになっています。とは言っても、PL/SQLとは違うので、どこで汎用的かと言われると難しいです。
PL/SQLとは違いがありますが、大枠としては似ている部分は多いと思います。
■ストアドプロシージャの作成
ストアドプロシージャの作成にはCREATE PROCEDURE命令を使います。
DELIMITER // CREATE PROCEDURE test_proc(in f int) BEGIN INSERT INTO test_table(val) VALUES(f); END; // DELIMITER ;
DELIMITER命令は、文の区切り文字(デリミタ)を変更します。
わかりづらいのですが、CREATE PROCEDURE命令は、「CREATE PROCEDURE」から「END;//」までが1つの文になり、その中で実行する命令を書くので、例えば、
CREATE PROCEDURE test_proc(in f int) BEGIN INSERT INTO test_table(val) VALUES(f); END; ;
と、DELIMITER無しにすると、「CREATE PROCEDURE」が「VALUES(f);」で終了してしまい、エラーになってしまいます。これを回避するために一時的にデリミタを//にしています。
これで定義した後に、
CALL test_proc(1);
とすると、INSERT INTOが実行されるのがわかると思います。
■ストアドプロシージャの削除
削除にはDROP PROCEDURE文を使います。DROP TABLE等と同様に、IF EXISTSを付けることができるので、CREATEの前に書いておくと便利かと思われます。
■ストアドファンクション
戻り値が無いものをプロシージャと呼ぶのに対し、戻り値があるものはファンクションと呼びます。
DELIMITER // CREATE FUNCTION test_func(f int) RETURNS int DETERMINISTIC BEGIN RETURN (f + 2); END; // DELIMITER ;
基本的にはプロシージャと同様ですが、いくつか違う点があります。
・引数にinが不要
プロシージャの引数の先頭のinは、「この値は入力値です」というのを指示するためのもので、プロシージャの場合はoutという指定もできます。これはPHPで言うところのリファレンス渡しに近いものになります。
ファンクションの場合はRETURNで戻り値を指定するので不要です。
・戻り値の型の指定
CREATE FUNCTIONの引数リストの後に、「RETURNS int」というのがあります。ここで戻り値の型を指定します。(この場合はint)
・DETERMINISTIC
これを付けないで定義しようとすると、
ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)のようなエラーが発生する場合があります。
入力値が同じ場合に出力値が同じ場合はDETERMINISTIC、そうでない場合はNOT DETERMINISTICを指定します。バイナリログの記録に関わるようです。
SET GLOBAL log_bin_trust_function_creators = 1;で回避することもできます。
ファンクションはSELECTで呼び出します。
test@localhost[testdb]> select test_func(1); +--------------+ | test_func(1) | +--------------+ | 3 | +--------------+
■変数の定義
DROP FUNCTION IF EXISTS test_func2; DELIMITER // CREATE FUNCTION test_func2(f int) RETURNS int DETERMINISTIC BEGIN DECLARE ret int; SET ret = f + 2; RETURN ret; END; // DELIMITER ;
内部で使う変数の定義にはDECLARE文を使います。
DECLARE文は全てBEGINの直後に書く必要があります。ルーチンの途中に書くことはできません。
... BEGIN DECLARE ret int; SET ret = f + 2; DECLARE ret2 int; ...
のようなのはエラーになります。
変数に値を代入するにはSET文を使います。
■カーソル
ストアドでよく使う処理として、「SELECTの結果を1行毎に何か処理したい」ということだと思います。PHPのforeach的なものです。
これを実現するにはカーソルというものを使います。
DROP TABLE IF EXISTS test_table; CREATE TABLE test_table ( a int, b int, c int); INSERT INTO test_table(a, b, c) VALUES(1, 2, 0); INSERT INTO test_table(a, b, c) VALUES(2, 3, 0); INSERT INTO test_table(a, b, c) VALUES(3, 4, 0); DROP PROCEDURE IF EXISTS test_proc2; DELIMITER // CREATE PROCEDURE test_proc2() BEGIN DECLARE eod tinyint; DECLARE in_a, in_b int; DECLARE out_c int; DECLARE cr1 cursor FOR SELECT a, b FROM test_table; DECLARE continue handler FOR not found SET eod = 1; SET eod = 0; OPEN cr1; FETCH cr1 INTO in_a, in_b; WHILE eod = 0 DO SET out_c = in_a * in_b; UPDATE test_table SET c = out_c WHERE a = in_a AND b = in_b; FETCH cr1 INTO in_a, in_b; END WHILE; CLOSE cr1; END // DELIMITER ;
カーソルは、SELECTの戻り値のポインタ的なもので、cursor型として定義します。
「DECLARE cr1 cursor FOR」の後に、そのカーソルで呼び出したいSQLを記述します。
「DECLARE continue handler FOR not found SET eod = 1;」は、カーソル呼び出しの際に、データが存在しなくなったら変数eodに1をセットするというhandlerを定義します。これでSELECTが終了したかどうかを判定します。
カーソルのDECLAREは通常変数のDECLAREの後に定義する必要があります。
DECLARE cr1 cursor FOR SELECT a, b FROM test_table; DECLARE out_c int;
のようにしてしまうと、
ERROR 1337 (42000): Variable or condition declaration after cursor or handler declaration
というエラーになります。
後はカーソルをOPENし、FETCHで値を取得するとINTOで指定した変数に代入され、それを処理します。
これを実行すると、
test@localhost[testdb]> SELECT * FROM test_table; +------+------+------+ | a | b | c | +------+------+------+ | 1 | 2 | 0 | | 2 | 3 | 0 | | 3 | 4 | 0 | +------+------+------+ 3 rows in set (0.01 sec) test@localhost[testdb]> CALL test_proc2(); Query OK, 1 row affected (0.01 sec) test@localhost[testdb]> SELECT * FROM test_table; +------+------+------+ | a | b | c | +------+------+------+ | 1 | 2 | 2 | | 2 | 3 | 6 | | 3 | 4 | 12 | +------+------+------+ 3 rows in set (0.00 sec)
cが反映されているのがわかると思います。
その他、詳しくはMySQLのリファレンスマニュアルを参照してください。
satoです。
弊社では、CubeCakeという、CakePHPでXOOPS開発ができるモジュールを配布しております。
CakePHPの手軽さをモジュール開発にそのまま利用できる便利なものではあるのですが、いくつか癖がありますので、そのあたりを紹介したいと思います。
(その1 と書いてありますが、その2があるかは未定です)
・ユーザ認証
CakePHP側のACLは使うのが難しいと思います。
手軽なのは、controllers/app_controller.phpに
のようなのを用意しておくと、手軽に利用できると思います。
同様に、app_controller.phpやapp_model.phpに、XOOPSでよく使うものを組み込んでおくだけでかなり楽になります。(xoops_redirectとか)
・シェルから叩く場合
CakePHPには、vendors/shellsに、Shellクラスを継承したクラスを置くことで、シェルから叩くプログラム(バッチ処理など)を簡単に作れる機構が存在します。
しかし、これを普通にCakePHPの方法で実行すると、CakePHPだけで完結しようとしてしまうため、XOOPSの各種設定が読み込まれずにいろいろ問題が起きます。(DBの情報を取得できない等)
この場合、以下のコードをvendors/shellsに置くスクリプトの先頭に記述すると綺麗(?)にXOOPSを初期化してくれます。
(もう少しスマートな書き方にできると思うので、整備して後日本体に反映したいと思います)
---
紹介できる内容が用意できたらまた紹介したいと思います。
まだいくつか問題がありますが、便利なので是非試してみてください。
弊社では、CubeCakeという、CakePHPでXOOPS開発ができるモジュールを配布しております。
CakePHPの手軽さをモジュール開発にそのまま利用できる便利なものではあるのですが、いくつか癖がありますので、そのあたりを紹介したいと思います。
(その1 と書いてありますが、その2があるかは未定です)
・ユーザ認証
CakePHP側のACLは使うのが難しいと思います。
手軽なのは、controllers/app_controller.phpに
protected function getUser() { global $xoopsUser; return $xoopsUser; }
のようなのを用意しておくと、手軽に利用できると思います。
同様に、app_controller.phpやapp_model.phpに、XOOPSでよく使うものを組み込んでおくだけでかなり楽になります。(xoops_redirectとか)
・シェルから叩く場合
CakePHPには、vendors/shellsに、Shellクラスを継承したクラスを置くことで、シェルから叩くプログラム(バッチ処理など)を簡単に作れる機構が存在します。
しかし、これを普通にCakePHPの方法で実行すると、CakePHPだけで完結しようとしてしまうため、XOOPSの各種設定が読み込まれずにいろいろ問題が起きます。(DBの情報を取得できない等)
この場合、以下のコードをvendors/shellsに置くスクリプトの先頭に記述すると綺麗(?)にXOOPSを初期化してくれます。
(もう少しスマートな書き方にできると思うので、整備して後日本体に反映したいと思います)
if (!isset($_SERVER['REMOTE_ADDR'])) { $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; } if (!isset($_SERVER['REQUEST_METHOD'])) { $_SERVER['REQUEST_METHOD'] = 'GET'; } $xoopsOption = array(); $xoopsOption['nocommon'] = true; require_once(APP.'../../mainfile.php'); if (!isset($_SERVER['REQUEST_URI'])) { $_SERVER['REQUEST_URI'] = XOOPS_URL.'/modules/cubecake/'; } require_once XOOPS_ROOT_PATH . "/include/functions.php"; require_once XOOPS_ROOT_PATH . "/class/xoopsobject.php"; $root=&XCube_Root::getSingleton(); if(!is_object($root->mController)) exit(); $root->mController->_setupFilterChain(); $root->mController->_processFilter(); $root->mController->_setupErrorHandler(); $root->mController->_setupEnvironment(); $root->mController->_setupLogger(); $root->mController->_setupDB(); $root->mController->_setupLanguage(); $root->mController->_setupTextFilter(); $root->mController->_setupConfig(); $root->mController->_setupDebugger(); $root->mController->_processPreBlockFilter(); //$root->mController->_setupSession(); //$root->mController->_setupUser(); $root->mController->setupModuleContext(); $root->mController->_processModule(); $root->mController->_processPostFilter();
---
紹介できる内容が用意できたらまた紹介したいと思います。
まだいくつか問題がありますが、便利なので是非試してみてください。