CakePHP+MySQLで、数値型カラムの結果を文字列ではなく数値で取得する

CakePHP+MySQLの環境で数値型カラムのデータを取得した戻り値も文字列になる。 これが問題となった事象のつぶやきに始まり、模索、原因究明、解決、ブログまとめ(http://t.co/u0EFeEKYFO)までの流れです。 ブログ記事の理解の助けにもなるのではないでしょうか。 なお、数値を文字列として返すDBIの仕様そのものは、問題ではなくむしろ安全であるとの見解が、タイムラインの最後の方にあります。
0
まわたりなおと @mawatarin

CakePHPのRequestHandlerComponentでJsonViewを返す際、型の指定ってできないのかな?integerで受け取りたいんだけど、stringになってる。

2013-08-22 13:46:14
まわたりなおと @mawatarin

フォーラムでも同じようなことがあがってるな。 cakephp と angularjs http://t.co/Ft1gHDPRtM

2013-08-22 13:49:46
まわたりなおと @mawatarin

Cake側でやるんなら、ビューファイルを作って、レスポンスデータを加工するのが良いのかな?

2013-08-22 13:51:42
まわたりなおと @mawatarin

へー、CakePhp-Backbone-Pluginなんてものがあるのか。コンポーネントがパッケージされてる。よくやるJSONの加工なんかが書かれてるみたい。 https://t.co/WaM7o6CHtM

2013-08-22 14:13:20
まわたりなおと @mawatarin

ビューファイルを作って、intval()してみたんだけど、JSONは、stringのままだなー。うーん、どうすればいいんだろうか。

2013-08-22 17:00:14
まわたりなおと @mawatarin

booleanがstringになるようなことはないから、何かやれば、できるんじゃないかと思うんだけどなー。

2013-08-22 17:01:42
まわたりなおと @mawatarin

@mawatarin 訂正。ただの勘違い。できてた。

2013-08-22 17:05:20
まわたりなおと @mawatarin

JSON云々じゃなくて、$this->model->find('all')の結果が、そもそもstringになっちゃってるな。

2013-08-22 17:36:24
まわたりなおと @mawatarin

見つけた。これかなー? int型の列がDBから文字列として引き出されているのは、既知の問題なのか。チケットも上がってる。 int columns are pulled as string from DB in CakePHP http://t.co/MwWJ8uNsot

2013-08-22 17:43:49
まわたりなおと @mawatarin

解決策が見つかるまで、afterFindコールバックで手動キャストするよう指南してある。CakePHP3.xで修正されるかもしれないってことらしい。(公式回答ではない)

2013-08-22 17:47:36
まわたりなおと @mawatarin

今回は1カ所1回だけだから、JS側で処理するか、json/index.ctpで処理するかしよう。

2013-08-22 17:47:46
まわたりなおと @mawatarin

tinyint(1)は、booleanにキャストするのにな。int(11)もintegerにしてくれれば良いのに。

2013-08-22 17:53:53
cakephper ichikawa @cakephper

@mawatarin PDOの問題かも。PHP5.3のMySQL NDってのを使えば解決するかも http://t.co/F0QWnQisFt

2013-08-22 18:06:15
まわたりなおと @mawatarin

@cakephper なるほど。情報ありがとうございます。ちょっと調べてみます。

2013-08-22 18:07:18
まわたりなおと @mawatarin

@cakephper 提供いただいた情報をもとに試してみましたが、状況変わらずでした。mysqlndに関しては、php5.4からはデフォルトで入ってるみたいです。 http://t.co/BvniAI54jz phpinfoでも有効になっているのを確認しましたが、ダメでした。

2013-08-22 22:21:35
まわたりなおと @mawatarin

@cakephper 取り急ぎ、状況報告まで。もうちょっと掘り下げてみたり、別のやり方がないか探してみます。ありがとうございました。

2013-08-22 22:23:56
cakephper ichikawa @cakephper

@mawatarin ダメでしたか。。。こちらでも試してみますー

2013-08-22 22:32:36
まわたりなおと @mawatarin

@cakephper 追伸です。 素のPHP(PDO, mysqli)でセレクトしてみても、int(11)はstringで出てきました。 フレームワーク側でうまいことやってくれたりしないかなと思いFuelPHP(PDO)でも試してみましたが、結果は同じでした。

2013-08-23 09:49:01
まわたりなおと @mawatarin

@cakephper ここらで調査は、いったんクロージングします。アドバイスありがとうございました。

2013-08-23 09:50:27
cakephper ichikawa @cakephper

@mawatarin ありがとうございました。PDOでintで取得できる方法を探って試してみます

2013-08-23 10:33:47
cakephper ichikawa @cakephper

@mawatarin PDOのコンストラクタのフラグオプションで、PDO::ATTR_EMULATE_PREPARES => falseをセットするとintで返ってきました。

2013-08-23 11:50:27
まわたりなおと @mawatarin

@cakephper おおお。こちらの環境でも確認できました!ありがとうございます。

2013-08-23 11:58:30
cakephper ichikawa @cakephper

@mawatarin Cakeの場合も出来るようになったので、後でブログにまとめますね

2013-08-23 11:58:51
まわたりなおと @mawatarin

@cakephper おお。それは助かります。僕もCakePHPでRESTful APIを作ってBackbone.jsと連携させる方法をブログにまとめます。

2013-08-23 12:13:31
まわたりなおと @mawatarin

先ほど知ったPDO::ATTR_EMULATE_PREPARESについて調べてみたんだけど、これは面白いな。セキュリティ面でも、このアトリビュートについて知っておかないといけないことがある。ググっても1万件弱しか情報が出てこないんだけど、もっと知られるべきだ。

2013-08-23 12:46:44