findのfieldsにconcatを使う際の疑問
今日はちょっとした疑問から。
例えば「ユーザ」というモデルがあって、フィールドが
- id
- name_l
- name_f
のように苗字と名前が分かれていた場合に、「User->find(“list”)」で取得するリストを「array(id => name_l.name_f」にするにはどうしたらいいか?ということなんですけれども、こういう場合プレーンなSQLならconcat()*1 を使って、
select id, concat(name_l, name_f) as name from users
とやればidと結合されたnameのフィールドが取得されますよね。
じゃあCakeでやってみましょう。
fieldsにconcatを入れてみる
$fields = array( "id", "concat(name_l, name_f) as name" ); $users = $this->User->find("all", array("fields" => $fields)); // リストにするならこの後に $users = Set::combine($users, "{n}.User.id", "{n}.User.name"); // こう書く
すると、concat自体は成功するけど、$usersに代入されるデータは
$users = array( array( "User" = array( "id" => "1" ), array( "name" => "苗字名前" ) ), );
こういう風になってしまうわけですよ。
キーがUserの配列に内包されない*2 からcombineしようと思ってもエラーになってしまうという…。
じゃあdisplayFieldにconcat(name_l, name_f)をしたらどうか?と思って試してみました。
displayFieldにconcatを入れてみる
$this->User->displayField = "concat(name_l, name_f) as name"; $users = $this->User->find("list");
これでもやっぱりエラー。というのも実際に吐き出されるクエリは、
select id, User.concat(name_l, name_f) as name from users
という感じで、User.concat()の部分で文法エラーになってしまう。
結局
仕方が無いので、最初の方法でfind(“all”)したデータを整形してSet::combine()する方法をとりましたが、スマートじゃないですよね。
$fields = array( "id", "concat(name_l, name_f) as name", ); $tmpUsers = $this->User->find("all", array("fields" => $fields)); foreach ($tmpUsers as $tmpUser) { $users[] = array( "User" => array( "id" => $tmpUser['User']['id'], "name" => $tmpUser[0]['name'] ) ); } $users = Set::combine($users, "{n}.User.id", "{n}.User.name");
CakePHPなら何か方法があるんじゃないかと思うのですが、もしご存知の方がいたら教えていただけないでしょうか。お願いいたしますm_ _m
コメント
同じ悩みを抱えてgoogle様に聞いていましたが初心にもどりマニュアルを眺め下記の様にすれば望みの形になりました。
Set::Combine($d, ‘{n}.user.id’, array(‘{0} {1}’, ‘{n}.user.name_l’, ‘{n}.user.name_f’));
http://book.cakephp.org/ja/view/662/combine
takuro様、ご丁寧に教えていただき本当にありがとうございます。
大変参考になりました。Cakeはちゃんと方法を用意してくれているのですね。