常識かもしれませんが、明言されている記事が見つからなかったのでエントリー。
動作確認バージョンは毎度のBeta 1.2.0.6311です。
queryとfind、findAllでの返り値の違い
例えばfindAllとqueryのそれぞれを使って全件取得した結果の違いを見比べてみます。(DBMSはMySQLを使用)
まずfindAllを使う場合。
$this->User->findAll();
の結果は
Array
(
[0] => Array
(
[User] => Array
(
[id] => 1
[username] => aaa
[password] => xxx
)
)
[1] => Array
(
[User] => Array
(
[id] => 2
[username] => bbb
[password] => yyy
)
)
)
となります。
次にqueryを使った場合。
$this->User->query('select * from users');
の結果は
Array
(
[0] => Array
(
[users] => Array
(
[id] => 1
[username] => aaa
[password] => xxx
)
)
[1] => Array
(
[users] => Array
(
[id] => 2
[username] => bbb
[password] => yyy
)
)
)
となります。
両者の違いは連想配列のkeyが'User'か'users'で異なる部分です。
このままでも使えることは使えますが、使用する側(コントローラやビュー)で配列のkeyが'User'と'users'で混在するのはシステムで統一感が無く、少し気持ち悪いです。
そこで次の方法を使えば、queryメソッドの場合も配列のkeyを'User'にすることが出来ます。
findAllと同じ返り値を得る方法
以下のようにテーブルに別名を付ける、その別名が配列のkeyとなります。
$this->User->query('select * from users as User');
とすると、
Array
(
[0] => Array
(
[User] => Array
(
[id] => 1
[username] => aaa
[password] => xxx
)
)
[1] => Array
(
[User] => Array
(
[id] => 2
[username] => bbb
[password] => yyy
)
)
)
の結果が返ってきます。
デバッグモードで表示されるSQLクエリを見ながら色々試してみた結果、この方法を見つけました。
結合させても大丈夫
結合させるテーブルにも別名をつけておくとアソシエーションを使った場合と同等の返り値を得ることが出来ます。
$this->User->query('select * from users as User left join posts as Post on Post.user_id = User.id');
の結果は
Array
(
[0] => Array
(
[User] => Array
(
[id] => 1
[username] => aaa
[password] => xxx
)
[Post] => Array
(
[id] => 1
[user_id] => 1
[title] => title1
[body] => hogehoge
)
)
[1] => Array
(
[User] => Array
(
[id] => 2
[username] => bbb
[password] => yyy
)
[Post] => Array
(
[id] => 2
[user_id] => 2
[title] => title2
[body] => hogehoge
)
)
)
となります。
ちなみにPostgreSQLでは
少し試した感じではMySQLほど簡単には出来ないようでした。
PostgreSQLでqueryメソッドを使った場合、
$this->User->query('select * from users');
の結果は
Array
(
[0] => Array
(
[0] => Array
(
[id] => 1
[username] => aaa
[password] => xxx
)
)
[1] => Array
(
[0] => Array
(
[id] => 2
[username] => bbb
[password] => yyy
)
)
)
と配列のkeyに'users'すら入りません。
次にMySQLではうまくいったテーブル名の別名をつけて、
$this->User->query('select * from users as "User"');
としても結果は変わらず。
色々試した結果、
$this->User->query('select id as "User__id", username as "User__username", password as "User__password" FROM users')
という風にフィールド名の別名として
keyにしたい文字 + __(アンダーバー2つ) + 列名
をセットすると、
Array
(
[0] => Array
(
[User] => Array
(
[id] => 1
[username] => aaa
[password] => xxx
)
)
[1] => Array
(
[User] => Array
(
[id] => 2
[username] => bbb
[password] => yyy
)
)
)
という期待する値が返ってきました。
取得したいフィールド全てに別名を付けていかないと駄目なようです。
使いどころ
queryメソッド自体、あまり出番が少ないかもしれませんが、
などの際にこの方法を知っておくと、コントローラーやビューで返り値を今までどおり扱えて便利かも知れません。