2009年1月13日

ヤフオク!

PHP SERIALIZEのススメ

  • このエントリーをはてなブックマークに追加

オークション事業部 開発部のやまけんです。

遅ればせながら、新年明けましておめでとうございます。

さて、オークションTechBlogも第4回目となりました。

今回はWebAPIとしての一つの形態であるPHP Serializeに関してお話します。

WebAPIは、一般的にはRESTと呼ばれるXMLを主体としたレスポンスを返却し、呼び側がXMLを解析するというものが主流となっています。
(RESTには、RESTfulと呼ばれる概念がありますが、それはまた別の機会にお話したいと思います)

さて、PHP Serializeですが、これはPHP言語で表現されるデータやクラスをサーバー側で文字列化して、呼び側でデータやクラスに復元するという手法です。

APIを利用する呼び側がPHPで実装されている場合には、REST形式のAPIよりも格段に利便性が高いです。なんせ解析処理が必要なく、そのまま関数を呼ぶイメージでデータが返却されるのですから。

オークションAPIでは、内部的にはXMLをベースとしており、今後逐次リリース予定であるPHP Serializeは、ベースであるXMLからPHP Serialize形式に変換しています。

つまり、
[XML] -> [PHP Serialize]
という変換が発生します。

PHP言語ではSimpleXMLというXML解析クラスが存在します。configureで "--enable-simplexml" を指定することで利用が可能です。

XMLからPHP Serialize形式に変換するには、上述したSimpleXMLを利用して
[XML] -> [SimpleXML] -> [PHP Serialize]
とするのが一番簡単です。

しかし、ここで1つ問題が発生します。

SimpleXMLクラスは、PHPのExtentionという位置づけのため、呼び側であるClientに必ず入っているとは言い切れないということです。

つまり、SimpleXMLをserialize(文字列化)しても、呼び側のPHP環境にSimpleXMLが存在しない場合には、復元ができないということです。

当然ながら、使い手の環境に制限を与えるのは極力ない方が良いので、さらに変換処理を一段挟み
[XML] -> [SimpleXML] -> [PHP array形式] -> [PHP Serialize]
とするのが、最も使い手(呼び側)にとって便利なPHP Serialize形式のAPIとなるでしょう。

SimpleXMLからPHPのarray形式に変換するサンプルコードをご紹介します。

 
<?php
function simpleXml2array($simpleXml, &$hash, $isRecursive = false) {
    if (!$isRecursive) {
        //
        // rootタグを設定。
        //
        $hash[$simpleXml->getName()] = null;

        //
        // 最上位タグの属性(attribute)を設定
        //
        foreach($simpleXml->attributes() as $key => $value) {
            $hash[$simpleXml->getName()][$key] = (string)$value;
        }
    }

    foreach($simpleXml->children() as $key => $value) {
        $values = (array)$value;

        if (0 < count($values)) {
            if (array_key_exists(0, $values)) {

                $setValue = null ;
                if (0 == strcasecmp((string)$value, "true")) {
                    $setValue = true;
                } elseif (0 == strcasecmp((string)$value, "false")) {
                    $setValue = false;
                } else {
                    $setValue = (string)$value;
                }

                if (array_key_exists($key, $hash)) {
                    if (! array_key_exists(0, $hash[$key])) {
                        $tmpHash = $hash[$key];
                        unset($hash[$key]);
                        $hash[$key][0] = $tmpHash;
                    }
                    array_push($hash[$key], $setValue);
                } else {
                    $hash[$key] = $setValue;
                }
            } else {
                //
                // 子要素あり。再帰。
                //
                $childHash = array();
                simpleXml2array($value, $childHash, true);
                if (array_key_exists($key, $hash)) {
                    if (! array_key_exists(0, $hash[$key])) {
                        $tmpHash = $hash[$key];
                        unset($hash[$key]);
                        $hash[$key][0] = $tmpHash;
                    }
                    array_push($hash[$key], $childHash);
                } else {
                    $hash[$key] = $childHash;
                }
            }
        } else {
            //
            // value=null
            //
            $hash[$key] = '';
        }
        //
        // set attributes.
        //
        foreach($simpleXml->$key->attributes() as $attr_key => $attr_value) {
            $hash[$key][$attr_key] = (string)$attr_value;
        }
    }
}

注:
上記のサンプルでは、型に関してはstring/booleanのみを意識しており、数値型の考慮はされてません。

PHP言語もウェブ開発言語として、広く一般的な言語となってきましたので、WebAPIの一つの表現手法としてPHP Serializeがもっともっと広まればいいなと思っています。

WebAPIは、日進月歩で扱いが簡単になっていっています。 APIを通して、より皆様との接点を増やしていければ幸いです!

Yahoo! JAPANでは情報技術を駆使して人々や社会の課題を一緒に解決していける方を募集しています。詳しくは採用情報をご覧ください。

  • このエントリーをはてなブックマークに追加