PHPでJSONを出力して、JavaScriptで取得する方法

February 12th, 2011

JSON(JavaScript Object Notation)というデータフォーマットを扱ってみたのでメモしておきます。

JSONは、XMLなどと同じようなテキストベースのファイル形式らしい。名前に「JavaScript」が入っているように、JavaScriptとの相性がとても良いらしいので、試しに扱ってみる事に。


PHPでJSONを出力する

JavaScriptでJSONを扱う前に、PHPで扱うJSONデータを出力しようと思います。

<?php
// JSON形式のテキストを生成する
$json = <<< JSON_DOC
    [
    {"name":"Google", "url":"https://www.google.co.jp/"},
    {"name":"Yahoo!", "url":"http://www.yahoo.co.jp/"}
    ]
JSON_DOC;

// JSON用のヘッダを定義して出力
header("Content-Type: text/javascript; charset=utf-8");
echo $json;
exit();
?>

上の方法は、JSON形式のテキストを自分で生成してますが、PHP5.2以上からはJSONに関しての関数が用意されているので、そちらを使った方が確実です。

PHP5.1以下の場合は、PEARの「Services_JSON」を利用してください。

<?php
$json = array(
    array('name'=>'Google', 'url'=>'https://www.google.co.jp/'),
    array('name'=>'Yahoo!', 'url'=>'http://www.yahoo.co.jp/'),
);

header("Content-Type: text/javascript; charset=utf-8");
echo json_encode($json); // 配列をJSON形式に変換してくれる
exit();
?>

JavaScriptでJSONデータを取得するオブジェクト

非同期通信を行う場合は、jQueryの$.ajax()を利用した方が簡単ですけど、XMLHttpRequest()を使ったコードをメモしておきます。

var myajax = function (options) {
    options = options ? options : {};

    this.isloader = false;
    this.request = false;
    this.url = options.url;
    this.params = options.params ? options.params : null;
    this.error = typeof options.error == 'function' ? options.error : function (data) { return false; };
    this.loaded = typeof options.loaded == 'function' ? options.loaded : function (data) { return false; };
};
myajax.prototype = {
    load : function () {
        if (this.getRequest()) {
            this.sendRequest();
        }
    },
    getRequest : function () { // 通信のリクエスト
        if (!this.url || this.isloader) return false;
        if (window.ActiveXObject) { // XMLHttpRequest未実装ブラウザ
            try { // MSXML2以降用
                this.request = new ActiveXObject('Msxml2.XMLHTTP');
            } catch (e) { // 旧MSXML用
                try {
                    this.request = new ActiveXObject('Microsoft.XMLHTTP');
                } catch (e2) {
                    this.request = false;
                }
            }
        } else if (window.XMLHttpRequest) { // XMLHttpRequest実装ブラウザ
            this.request = new XMLHttpRequest();
        } else {
            this.request = false;
        }
        return this.request ? true : false;
    },
    sendRequest : function () { // リクエストの送信
        var t = this;
        if (!t.request) return false;
        t.isloader = true; // 通信判定(重複通信を防ぐ)
        t.request.open('POST', t.url, true); // 初期化
        t.request.onreadystatechange = function () { // 進行状況の確認
            if (this.readyState == 4) { // 通信完了
                switch (this.status) {
                    case 200 : // 成功
                        var obj = eval(this.responseText); // オブジェクトに変換
                        t.loaded(obj);
                        break;
                    default : // 失敗
                        t.error(this.statusText);
                        break;
                }
                t.isloader = false;
                t.request = false;
            }
        };
        t.request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); // ヘッダ設定
        t.request.send(t.setParameter()); // 送信
    },
    setParameter : function () { // 送信パラメータの設定
        if (!this.params) return null;
        var result = '';
        for (var key in this.params) {
            var value = this.params[key];
            result += (result ? '&' : '') + key + '=' + encodeURIComponent(value);
        }
        return result ? result : null;
    }
};

非同期通信を実行する

document.body.onloadを使用した場合は、bodyタグより下に記述しないと、bodyタグが存在しません的なエラーが返されるので注意。

<body>
    <!-- bodyタグより下に記述 -->
</body>

<script type="text/javascript">
//<![CDATA[
    var ma = new myajax({ // myajaxオブジェクトを生成
        url : '/ajax/json.php',
        params : {},
        error : function (data) {
            console.log(data);
        },
        loaded : function (data) {
            console.log(data[0].name); // 出力結果:Google
        }
    });

    document.body.onload = ma.load(); // 通信実行
//]]>
</script>
February 12th, 2011