今回は、PHP用のライブラリとして、Syck for PHP、php_yaml、Spycの3つのライブラリを紹介します。
Syck for PHP
Syckは、Cで書かれたYAML用のライブラリです。もともとはRuby 1.8に付属しているライブラリですが、PHP用のバインディングが用意されています。
インストール
インストールは(リスト1)のように行ってください。
使い方
PHPにおけるSyckの使い方は、リスト2のとおりです。基本的に次の関数だけが用意されており、YAMLストリームの読み込みはできません。
- syck_load()
- YAMLドキュメントを読み込む
- syck_dump()
- データをYAMLドキュメントに変換する
syck_dump()において、日付と日時(timestamp)はDateTimeクラスのオブジェクトに変換されます。
日本語の扱い
読み込み(syck_load())については、EUCやUTF-8であればsyck_load()で問題ないようです。書き出し(syck_dump())については、日本語はたとえば「\xE3\x81\x84」のようにエンコードされます。エンコードされた文字列でもsyck_load()で問題なく読み込めますが、気になる場合はRubyの場合と同様にSyckのソースコードにパッチを当てることで、エンコードされるのを回避できます。詳しくはRubyでのSyckのセクションをご覧ください。
不具合
yck for PHPは、RubyのSyckと同じ不具合を抱えています。筆者が試したところ、その他に次のような不具合がありました。
- syck_load()
- 循環構造を持つデータがあるとエラーになる(リスト3)
- syck_dump()
- 独自クラスのインスタンスオブジェクトがYAMLへ変換できない
- 配列が循環構造を持っているとエラー(Segmentation fault)になる(リスト4)
syck_dump()を使うなら、現状ではインスタンスオブジェクトは諦めて、代わりに配列を使ったほうがよさそうです。
その他
PHPでは、無限配列(ArrayやList)と連想配列(HashやMap)の区別がありません。そのため、PHPの配列をsyck_dump()でYAMLドキュメントに変換するとき、YAMLのシーケンスに変換するのか、それともマッピングに変換するのかが問題になります。
実際の動作としては、次のようになるようです(リスト5)。
- インデックスが0から始まり、かつ連続していた場合はシーケンスに変換
- それ以外の場合はマッピングに変換
php_yaml
php_yamlはlibyamlのPHP用ラッパーです。libyamlを使っていますので、Syckと違い、YAML1.1の仕様に沿っています。PHPでYAMLパーサを使いたいなら、現在いちばんお勧めです。
なお余談ですが、作者であるrsky氏は、PHPの言語仕様を強化する拡張モジュールQIQを開発するなど、今注目のプログラマです。
インストール
コンパイルするにはlibyamlをあらかじめインストールする必要があります。以下の手順でlibyamlをインストールしてください(リスト6)。
続いて、php_yamlを次の手順でインストールします(リスト7)。コンパイルする前に、こちらのパッチ[1]を適用してください。
使い方
php_yaml 0.3.0 では以下の関数が用意されています[2]。
- yaml_parse($str [, $index [, $count [, $callbacks]]])
- YAML文字列を読み込む
- yaml_parse_file($str [, $index [, $count [, $callbacks]]])
- YAMLファイルを読み込む
- yaml_parse_url($str [, $index [, $count [, $callbacks]]])
- URLからYAMLドキュメントを読み込む
php_yamlの基本的な使い方は、リスト8のとおりです。
ストリームを読み込むときは、何番目のドキュメントを読み込むかをyaml_parse()またはyaml_parse_file()の第2引数で指定できます。また-1を指定すると、すべてのドキュメントを読み込み、配列に格納して返します。第3引数を指定すると、ストリームに含まれるドキュメント数が設定されます(リスト9)。
なお日付および日時のスカラー値は、デフォルトではパースされずに文字列となります。日付や日時をパースするには、ini_set() を使ってyaml.decode.timestampを1または2に設定します(リスト10)。
- init_set('yaml.decode_timestamp', 1) なら、1970年1月1日 00:00:00からの通算秒を返します
- init_set('yaml.decode_timestamp', 2)なら、関数date_create()を使ってDateTimeオブジェクトに変換されます
date_create()はPHP 5.1から利用可能なので、関数が存在することを確認してから使ってください。
日本語の扱い
筆者が試した限りでは、EUC-JPやShift_JISではエラーになりましたが、UTF-8であれば問題なく扱うことができました。
タグを変更する
クラスに対応するタグを登録するには、インスタンスオブジェクトを生成するような関数を定義し、それをコールバック関数としてyaml_parse()またはyaml_parse_file()の第4引数に指定します(リスト11)。
ただし、タグは「!tagname」ではなく「!<tagname>」と書かないといけないようです。
不具合
筆者が試した範囲では、以下のような不具合がありました。
- マッピングのマージ(<<)に未対応
- マッピングのデフォルト値(=)に未対応
- 値がないときにNULLにならず空文字列になる(パッチで修正済み)
- 「2008-01-01 12:34:56」のパターンの日時がパースできず文字列となる(パッチで修正済み)
- 'y'や'n'が文字列ではなく真偽値と見なされる[3]
その他
php_yamlはlibyamlを使っているだけあって、YAML 1.1の仕様に忠実です。PHPでYAMLパーサが必要なら、現時点でいちばんお勧めです。将来的にはyaml_emitter()が実装されることに期待しましょう。
Spyc
Spycは、PHPで実装されたYAML用ライブラリです。Pure PHPですので、拡張ライブラリがインストールできない場合には重宝します。ただし拡張ライブラリが使えるのであれば、速さの点でも機能の点でも、Syckやphp_yamlをつかうほうがよいでしょう。
インストール
インストールは、上記ページからspyc-0.3.beta.tar.gzをダウンロードして解凍し、spyc.php(PHP 4用)またはspyc.PHP 5(PHP 5用)を適切なディレクトリにコピーするだけです(リスト12)。
使い方
Spycの基本的な使い方はリスト13のとおりです。機能としては次の2つだけであり、YAMLストリームの読み込みはできません。
- Spyc::YAMLLoad($filename)
- YAMLドキュメントを読み込む
- Spyc::YAMLDump($data)
- データをYAMLドキュメントに変換する
またSpyc::YAMLLoad()の引数にはファイル名を指定するため、YAML文字列を読み込むことはできないようです。
タグを変更する
Spycはタグをサポートしていません。
日本語の扱い
日本語は、EUCまたはUTF-8であれば特に問題はないようです。Spyc::YAMLDump()において日本語がエンコードされることもありません。
不具合
筆者が試した限りでは、以下のような不具合がありました。
- Spyc::YAMLLoad()
- スカラーへのアンカーとエイリアスが解釈できない
- 「&m1 {A: 10}」のようにアンカーとデータを同一行に書くと解釈されない
- 日付や日時(timestamp)が未サポート
- 「null」と「~」が未サポート
- マッピングのマージが未サポート
- ブロックスタイルの文字列があると無限ループになる
- 値がない場合にnullではなく空文字列になる
- マッピングのキーに日本語を使用すると文字化けする
- ルート要素がフロースタイルだと解釈できない
- フロースタイルに改行が入っていると解釈できない
- Spyc::YAMLDump()
- ルート要素がスカラーだとエラーになる
- 配列のキーが数字であれば必ずシーケンスに変換される
- マッピングとシーケンスが混ざって出力されることがある(リスト14)
その他
Spycは、symphonyフレームワークなどで使われています。