ホームページ制作 オフィスオバタ

Uncaught SyntaxError: Unexpected token < in JSON at position 4に対処

HTMLとPHP間でデータ通信をするにはコツがいります。

平たく言うとJSONを使用すればできます。
ところが今回、JSONでエラーが発生し、処理が動作しないことがありました。

調べて対処できましたので、忘備録として記録します。

参考:JSONとは

通常はHTML→PHPへメールフォーム等でデータを送ることはできます。
しかし、PHP→からHTMLへ処理結果を送ることができません。

なぜならば、PHPの処理終了をHTMLが待たずに完了しているからです。

プログラムで処理結果通知をもらうためには、結果が到着するまで待つ必要があります。
これを同期通信といいます。

HTMLの場合、PHPに処理を投げても結果到着まで待つことができません。
この関係を非同期通信といいます。

非同期通信の関係で、処理結果をHTMLに渡すことができる機能がJSONと呼ばれています。
主に画像投稿をドロップで行う場合に使用します。

現象はこのような感じです

PHPからの戻り値を期待していたのですが、Uncaught SyntaxError: になりました。
そこでまず、何が起こったかを調べました。

ちなみにJSONはJavaScriptで記述されるため、Chromeのデバックモード(F12キーを押す)にすると、Javascriptのエラーやログなどを見ることができます。

こういった不測のエラー発生時に重宝します。

原因は意図しない内容が返されたことによるエラー

PHP側からの処理結果を受信する部分でエラーが発生していました。

PHP側の致命的エラーメッセージは、本来画面に表示されますが、JSONから呼び出した場合はJSONへ返されます。
本来ちゃんとしたフォーマットでPHPからJSONへ処理結果を通知するものですが、PHP致命的エラーのため、フォーマットを無視してエラーメッセージが送られたため、JSON側でエラーとなっていました。

つまり、今回はPHP側で致命的エラーが発生したことが原因です。
PHP側のエラーを直せばOKなのです。

ということでPHPで何エラーが起こったかを調べてみました。

とりあえず何が起こったかを詳しく見てみました。

エラー表示部分に「VM116:3」と表示されています。
この部分は、毎回表記は異なりますが、この部分をクリックするとエラーの詳細が表示されます。

早速表示してみたところ、以下のようなエラーが発生していました。

どうやら呼び出したPHP側で致命的エラーが発生しているようでした。
その内容がJSONを通じてHTML側に渡されたようです。

ちなみにエラーとなっているJSON側の命令は以下のものでした。

var res = JSON.parse(data.xhr.responseText);

エラーメッセージから内容を紐解くと、「存在しない関数をコールしています」というものでした。
そこで、PHP側のエラーの原因を修正したところ、無事エラーが直りました。

疑問:テスト環境ではエラーが出ないのに、サーバーUPでなぜ「存在しない関数コールエラー」になったのか?

ちなみに、今回テスト環境ではエラーにならないのに、サーバーへ上げたらエラーになってしまったのか引っ掛かりました。

ちなみにエラーとなった関数は「exif_read_data()」です。
画像のEXIF情報(画像の上位置、回転位置などの情報)を調べるための関数です。

PHPの標準関数なので、関数コールエラーになりえないと思っていました。
ただよくよく調べてみると、PHPの拡張関数ということがわかりました。
つまり、サーバーがPHPの拡張設定をしていない場合は存在しない関数になります。

今回使用したサーバーでPHPの拡張設定がされていないためでした。

どうにもならないため、今回は該当関数を呼ばないようにコメント化しました。
機能を一部削ることになりますが、サーバーが対応できていない以上、サーバーを引っ越すぐらいしか対応方法がありません。

JSONエラーはたいてい呼び出したプログラムでエラーが起こっている

JSONエラーなので、てっきりJavascriptの記述エラーなどを疑ってしまいがちです。
しかしながら、テスト環境等で問題なく動いている場合は、呼び出したプログラム側で問題が発生していることが多いです。

JSONで呼び出しているため、画面にプログラムエラーが表示されないため、調べるのが困難なだけです。
Chromeを使えば容易にプログラムエラーの内容を見ることができます。

最初これがわからず、またvar_dump()関数をいれてもJSONから呼び出した場合は表示されないため、調べるのにてこずりました。

でも、エラーを見る方法がわかれば、あとはいつも通りに調べてゆけばOKということを学びました。
今回もひとつ良い経験をいたしました。

モバイルバージョンを終了