LoginSignup
16
9

More than 5 years have passed since last update.

CakePHP3でJSONを返すだけのAPIを実装した時に起きた問題

Last updated at Posted at 2017-10-21

発生した問題

Cakeでjsonを返して、jQueryで処理しようとしたら、下記の問題発生

  • HTTPステータスが200(OK)でなのに、$.ajaxのfailに分岐してしまう
  • Responseにechoしたjson以外のものが混じっている

HTTPステータスが200(OK)なのに、$.ajaxのfailに分岐してしまう

failのstatusを見てみたら、parsererrorが返ってきていた。

  • Cake側で余計なheaderを付与していたこと
  • jQuery側で余計なdataTypeを指定していたこと

が問題っぽい。

php
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;
}
js
$.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を返す場合はレイアウトを出力しないように修正してみる

php
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に入っちゃってるのかな?
下記のように修正で解決

php
// 修正前
echo json_encode($results);

// 修正後
$this->response->body(json_encode($results));

最終的なコード

最終的に下記のようなコードにしたら上手くいった

php
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;
}
js
$.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側の処理が実行される

16
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
9