発生した問題
Cakeでjsonを返して、jQueryで処理しようとしたら、下記の問題発生
- HTTPステータスが200(OK)でなのに、$.ajaxのfailに分岐してしまう
- Responseにechoしたjson以外のものが混じっている
HTTPステータスが200(OK)なのに、$.ajaxのfailに分岐してしまう
failのstatusを見てみたら、parsererrorが返ってきていた。
- Cake側で余計なheaderを付与していたこと
- jQuery側で余計なdataTypeを指定していたこと
が問題っぽい。
if($this->request->is('ajax')) {
$query = $this->モデル名->find('all');
$results = $query->all();
//header('content-type: application/json; charset=utf-8'); この行が不要
echo json_encode($results);
return;
}
$.ajax({
url: 'url',
type: 'post',
contentType: 'application/json',
//dataType: 'json' この行が不要
}).done(function (data, status, jqXHR) {
// 成功時の処理
}).fail(function (jqXHR, status, error) {
// 失敗時の処理
});
上記のコメントアウトした行を削除することで、成功時の処理へ行くようになった。
サーバ側のMINEタイプとdataTypeの不整合で問題が起きていたっぽい?
jQuery側で自動判別してもらうことで解決した模様。
Responseにechoしたjson以外のものが混じっている
Chromeの開発者ツール - Network - Responseを見てみた。
するとjson以外に下記が入っていた。
HTMLタグ
<div>
<br>
<br>
<br>
<br>
<br>
<button id="btn-ajax" type="submit">ajax</button></div>
なんかHTMLのタグが入ってるー
なんとなくこれはCakePHPのViewが入っちゃってるんじゃなかろうかと思い、
jsonを返す場合はレイアウトを出力しないように修正してみる
if($this->request->is('ajax')) {
$this->viewBuilder()->autoLayout(false); // この行を追加
$this->autoRender = false; // この行を追加
$query = $this->モデル名->find('all');
$results = $query->all();
echo json_encode($results);
return;
}
警告文
Warning (512): Unable to emit headers. Headers sent in file=/Applications/MAMP/htdocs/cakephp3/src/Controller/xxxxxxxxxxxxxxxxxxxx.php line=193 [CORE/src/Http/ResponseEmitter.php, line 48]
Warning (2): Cannot modify header information - headers already sent by (output started at /Applications/MAMP/htdocs/cakephp3/src/Controller/xxxxxxxxxxxxxxxxxxxx.php:193) [CORE/src/Http/ResponseEmitter.php, line 148]
Warning (2): Cannot modify header information - headers already sent by (output started at /Applications/MAMP/htdocs/cakephp3/src/Controller/xxxxxxxxxxxxxxxxxxxx.php:193) [CORE/src/Http/ResponseEmitter.php, line 181]
Warning (2): Cannot modify header information - headers already sent by (output started at /Applications/MAMP/htdocs/cakephp3/src/Controller/xxxxxxxxxxxxxxxxxxxx.php:193) [CORE/src/Http/ResponseEmitter.php, line 181]
なんかWarningとか出てるー
なんとなくだけど何も設定してないから、echoしたやつがheaderに入っちゃってるのかな?
下記のように修正で解決
// 修正前
echo json_encode($results);
// 修正後
$this->response->body(json_encode($results));
最終的なコード
最終的に下記のようなコードにしたら上手くいった
if($this->request->is('ajax')) {
$this->viewBuilder()->autoLayout(false);
$this->autoRender = false;
$this->response->charset('UTF-8');
$this->response->type('json');
$query = $this->モデル名->find('all');
$results = $query->all();
$this->response->body(json_encode($results));
return;
}
$.ajax({
url: 'url',
type: 'post',
contentType: 'application/json',
}).done(function (data, status, jqXHR) {
// 成功時の処理
}).fail(function (jqXHR, status, error) {
// 失敗時の処理
});
参考サイト
【CakePHP3.x】jsonを返すapiを作りたい
【CakePHP3.x】Unable to emit headers. Headers sent in file=... line=xxx
ajax通信でステータスコード200が返ってきているのにerror側の処理が実行される