こんにちは!ぐちです。
CakePHPのfind
CakePHPを普段から使われている方ならご存知かもしれませんがモデルのfind()を使ったクエリ結果にはモデル名が含まれるんですよね。検索結果をいじくる場合には連想配列のインデックスにモデル名を指定しないといけません。
{
response: {
status: "ok",
data: [
{
TblHoge: {
id: "1",
name: "ほげ"
}
},
{
TblHoge: {
id: "2",
name: "はげ"
}
}
]
}
}
上記のようにTblHogeがレスポンスコードに含まれてしまいます。下記のようにfind(‘all’)をシンプルに呼ぶとこうなってしまいます。
<?php
App::uses('ApiAppController','Controller');
class ApiController extends ApiAppController {
public $uses = array('TblHoge');
public function index() {
$ret = $this->TblHoge->find('all');
$this->viewClass = 'Json';
$this->set('response', array('status' => 'ok','data' => $ret));
$this->set('_serialize', array('response'));
}
}
モデル名を削除する
たった1行追加するだけでレスポンスコードからモデル名を削除することができます。下記のコードをご覧ください。
public function index() {
$ret = $this->TblHoge->find('all');
$ret = Hash::extract($ret,'{n}.'.$this->TblHoge->name); // モデル名を削除する
$this->viewClass = 'Json';
$this->set('response', array('status' => 'ok','data' => $ret));
$this->set('_serialize', array('response'));
}
コメントを入れていますがこの処理を追加するだけでレスポンスコードからモデル名を削除することができます(下記レスポンスコード参照)。一般的なJSONってこっちの形ですよね。なぜCakePHPはモデル名が含まれる仕様となったのか。必要性があるのかもしれませんね。
{
response: {
status: "ok",
data: [
{
id: "1",
name: "ほげ"
},
{
id: "2",
name: "はげ"
}
]
}
}
適切な場所へ
上記の例だとコントローラからfind()を呼ぶたびにわざわざ書かないといけなくなるのでAppModelのコールバックメソッドに記述すれば毎回書かなくて済みます。
class AppModel extends Model {
public function afterFind($results, $primary = false) {
return Hash::extract($results,'{n}.'.$this->name);
}
}
AppModelのafterFind()は各モデルで処理されたfind()系の後に呼ばれるメソッドです。第1引数に結果が格納されているのでここに実行時のモデル名を指定して削除すればレスポンスコードからなくなりキレイになります。
他にも検索結果に対してデータ整形等を行う場合もここに書けば大丈夫です。逆に各モデルで処理される前に呼ばれるコールバックメソッドや更新系の場合など様々なコールバックメソッドが用意されていますので公式ドキュメント等でご確認ください。