今回の疑問
今日もFuelPHPとPostgreSQLでシステム開発しております。
modelクラスで高度なSELECT文の実行結果を返すメソッドを書いてます。 例えばこんな感じ。
$sql = <<<EOT SELECT a, b, c, x, y, z FROM ( SELECT … FROM … ) LEFT JOIN ( SELECT … FROM … ); EOT; return DB::query($sql)->as_assoc()->execute();
結果に含まれるa, b, cの取りうる範囲がそれぞれ違っていて、その値の範囲を表組みする前にチェックしておくのも大事で。
クエリー結果を単純に連想配列管理してしまうと、最終的に欲しいデータ(例でいうところのxやyやz)を簡単に取り出しにくくなるじゃないですか。
たまたま、a, b, c が数値だったので、a~cを連結した文字列を作って個々の連想配列でx,y,zを管理しようと考えて、こんなふうにしました。
$dat_x = array(); $dat_y = array(); $dat_z = array(); foreach ($result as $rec) { $dat_x[$rec['a'].'<>'.$rec['b'].'<>'.$rec['c'] = $rec['x']; $dat_y[$rec['a'].'<>'.$rec['b'].'<>'.$rec['c'] = $rec['y']; $dat_z[$rec['a'].'<>'.$rec['b'].'<>'.$rec['c'] = $rec['z']; }
これってcontrollerクラスの仕事なのかなぁ。
こうやって加工したのを、viewクラスでループ変数で回して表組みするんですけど、効率よくする方法ってあるのかなぁ。
as_assoc()でなく、as_object()を試す
アドバイス、いただきました。 ありがとうございます。 引用しちゃいます。
@michieru as_object()で結果をオブジェクトにしたほうがいいと思います http://t.co/iR8MTU4vRU
— 『はじフレFuelPHP』 (@fuelphp1st) June 18, 2014
そういえば、as_object()って試したことがなかった。 書き換えてみました。
$sql = <<<EOT SELECT a, b, c, x, y, z FROM ( SELECT … FROM … ) LEFT JOIN ( SELECT … FROM … ); EOT; return DB::query($sql)->as_object()->execute()->as_array();
$dat_x = array(); $dat_y = array(); $dat_z = array(); for ($i = 0; $i < count($result); $i++) { $dat_x[$result[$i]->a.'<>'.$result[$i]->b.'<>'.$result[$i]->c = $result[$i]->x; $dat_y[$result[$i]->a.'<>'.$result[$i]->b.'<>'.$result[$i]->c = $result[$i]->y; $dat_z[$result[$i]->a.'<>'.$result[$i]->b.'<>'.$result[$i]->c = $result[$i]->z; }
クエリーの結果のカラム名(フィールド名)をプロパティとして利用できて、読みやすくなりました。
これがもし、こうだったら。
$sql = <<<EOT SELECT a || '<>' || b || '<>' || c as k, x, y, z FROM ( SELECT … FROM … ) LEFT JOIN ( SELECT … FROM … ); EOT; return DB::query($sql)->as_object()->execute();
モデル側でas_array()してないので、受けるコントローラー側でas_array()できますね、こうなります。
$dat_x = $result->as_array('k', 'x'); $dat_y = $result->as_array('k', 'y'); $dat_z = $result->as_array('k', 'z');
コントローラー側で連結処理せずにクエリー結果上で連結させてしまえば、連想配列として管理するのは簡単になりますね。
ただ、これをやってしまうと、クエリー結果からaやbやcの値の範囲をチェックすることができなくなる。 何かもう一工夫必要な感じに。