前回にも書きましたけど php 5.3 になっていろいろと変更されたことがあるようで、結構大変です。
嘆いていてもしょうがないので、標準 API の mysqli_* シリーズを使って書き直しているのですが、MDB2 シリーズとの互換性も持ちたいため、かなり難儀しています。
昨今の流れとして、SQL を発行するときはプリペアドステートメントを使うため mysqli_stmt_* シリーズを使って書いているのですが、MDB2 を使用するときと同じインターフェイスにしないと駄目なため class を使って記述をしたい、自作の DB 操作関数群をそういう風に作ったため、なのですが、これが地獄の始まり…
なお、基本的に mysqli_ シリーズの関数は手続き型ではなくオブジェクト指向型を使っています。
- SQL を発行するとき
まぁ、mysqli_stmt_bind_paramを使用するわけですが、mysqli_stmt::bind_param の第二引数以降は参照渡しで定義されています。で、汎用的な class を作っているため、この引数は可変です。私の場合、渡された引数を array 型で構築して、そのまま関数に渡せばいいや。と思ってそのように書いて、call_user_method_arrayという関数を使用することにしました。そしてこの関数は、リファレンスマニュアルにあるとおり、非推奨になっており、call_user_func_arrayを使うことになります。
ここまでは割と問題なくかけるのですが…以下のように書いたら動かない。警告が出て失敗してしまう。で、まず、これでかなり悩んだのですが…$db = new mysqli( IP, USERNAME, PASSWORD, DBNAME ); $s = ''; $t = array(); foreach ( $params as $p ) { if ( is_bool($p) or is_int($p) ) { $s .= 'i'; $t[] = $p; } elseif ( is_float($p) ) { $s .= 'd'; $t[] = $p; } elseif ( is_string($p) ) { $s .= 's'; $t[] = $p; } else { // blob 型はまだ $s .= 'b'; } } $stmt = $db->stmt_init(); if ($stmt->prepare($query)) { call_user_func_array(array($stmt,'bind_param'),array_unshift($t, $s)); $stmt->execute(); }
結論。bind_param の2番目以降の引数は参照渡しにしないと駄目。具体的には、foreach で配列を作っているときに参照渡しにする感じ?なんだろうけど…受け取る訳じゃないのに参照渡しって変だよなぁ。 - 値を受け取るとき
まぁ、mysqli_stmt_bind_resultを使うわけですが…これも同じように参照渡し&可変引数なわけで……これかなり悩みました。検索しても大してヒットしないし。で、やっとたどり着いたのが海外の掲示板。要は $$ を二つ重ねて、変数を動的に作る…のかな?初めて見た構文だ(^^ゞ
で、結果を連想配列で受け取りたかったので以下のように記述$rslt = $stmt->result_metadata(); $header = array(); while ($field = $rslt->fetch_field()) { $key = strtolower($field->name); $header[] = $key; } $data = array(); foreach ($header as $key) { $$key = NULL; $data[$key] = &$$key; } call_user_func_array(array($stmt,'bind_result'), $data);
これで何とか動作…しているといいな。
しかし php 関連の検索ってノイズ乗りすぎでひどいな…あと、php 5.3 になっていろいろ関数仕様が変更されて大変みたい?