CodeZine(コードジン)

特集ページ一覧

PHPでのストリーム処理の実装

PHPエクステンションの作り方 第6回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2014/01/21 14:00
目次

コンテキストを通じてパスワードを設定する

 コンテキストとは多少なじみがない方もいるのではないでしょうか。PHPのストリームでは、fopen()関数でストリームをオープンするときにパラメータを設定できます。モジュールを実装する側としてはコンテキストの方が実装は簡単ですが、利用者にとっては多少敷居が高くなってしまいます。ただし、実際の設定方法は以下のようにそれほど難しいものはありません。

コンテキストの設定方法
$opt = array(
    'pzip' => array('password' => 'abcdefg')  // ……(1)
);
$context = stream_context_create($opt);        // ……(2)
$fp = fopen($path,"rb",0,$context);  // ……(3)

 (1)のように、使用するスキーム名とキー値の2次元配列形式にして値を設定します。次に、(2)stream_context_create()関数でコンテキスト変数を作成します。(3)fopen()する際に、作成したコンテキスト変数を引数に設定します。

 続いて、設定した値をモジュール側で取得するコードを紹介します。

コンテキストに設定した文字列を取得する方法(pzip_stream.cの抜粋)
zval **tmpzval;  // ……(1)
if(php_stream_context_get_option(context,"pzip","password",&tmpzval) == SUCCESS){  // ……(2)
    if(Z_TYPE_PP(tmpzval) == IS_STRING && Z_STRLEN_PP(tmpzval)){                                   // ……(3)
    password = estrdup(Z_STRVAL_PP(tmpzval));  // ……(4)
    }
}

 コンテキストに設定した文字列はPHP側から設定されてきますので、つまり、モジュール側ではzval形式の変数になります。従って、(1)のようにzval変数を用意します。(2)でコンテキストからスキーム名とキー値を指定して用意したzval変数を通じて値を取得します。(3)ではそのzval変数が文字列型であることを確認し、(4)でchar*型に変換して値を設定しています。このように、URLをパースする労力に比べると遙かに短いコードですませることができます。

ストリームラッパーとして登録する

 続いて、作成したphp_stream_pzip_opner関数をストリームラッパーとして登録するための(1)構造体php_stream_wrapper_opsを用意します。この構造体は、php_stream_opsと非常に似ていますが、unlinkや、renameなどもあるように開いたストリームを扱うのではなくURL文字列によってリソース内のデータ操作を扱うためのものです。この構造体には、(2)先ほど作成したストリームをオープンするための関数を登録します。次に、その構造体をさらに(3)php_stream_wrapper構造体を用意し、(4)のように設定します。

ストリームラッパーを登録するための構造体の用意(pzip_stream.cの抜粋)
static php_stream_wrapper_ops pzip_stream_wops = {  // ……(1)
    php_stream_pzip_opener,                         // ……(2)
    NULL,  /* close */
    NULL,  /* fstat */
    NULL,  /* stat */
    NULL,  /* opendir */
    "pzip wrapper",
    NULL,  /* unlink */
    NULL,  /* rename */
    NULL,  /* mkdir */
    NULL,  /* rmdir */
};

php_stream_wrapper php_stream_pzip_wrapper = {  // ……(3)
    &pzip_stream_wops,                      // ……(4)
    NULL,
    0  /* is_url */
};

 これで必要な関数や変数がすべてそろいましたので、モジュールとしてPHP側に識別できるようにします。これまで、関数やクラスを登録する際には、(1)PHP_MINIT_FUNCTION関数内で指定していましたが、ストリームラッパーも同様に(2)php_register_url_stream_wrapper()で設定します。

モジュールとして登録する処理(pzip.cの抜粋)
PHP_MINIT_FUNCTION(pzip)  // ……(1)
{
   : (省略)
   php_register_url_stream_wrapper("pzip", &php_stream_pzip_wrapper TSRMLS_CC);  // ……(2)
    return SUCCESS;
}

 PHPでstream_get_wrappers()やphpinfo()を実行し、利用できるストリームとして登録した"pzip"という文字列が含まれていれば、正常に登録できたことを確認できます。

最後に

 今回は、PHPでのストリームの実装処理がどのようにできているかを実際にZipファイルの読み込みを通じて紹介しました。ストリームはPHPだけでも作成できる機能ですが、さまざまなリソースにアクセスするには通常はネイティブのライブラリが用意されており、それらを操作するクラスや関数を作成していたものに対して、多少の拡張で実装が可能です。

 PHPでは非常に多くの関数が用意されています。また、その拡張もこれまで紹介してきたとおりできますが、そのアクセス方法は実装者に依存してしまったり、詳細なアクセス方法を提供するために結果的に難解になってしまう場合があります。そのような場合の利用方法として、ストリームラッパーなどを用意すると、新たな関数を覚える必要がなくデータの操作が可能です。また、場合によってはPHPのプログラムを変更することなく実装できるケースもあります。

 このように、利用者のレベルや目的に応じたアクセス方法の提供ができます。

参考資料



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

バックナンバー

連載:PHPエクステンションの作り方

著者プロフィール

  • WINGSプロジェクト 小林 昌弘(コバヤシ マサヒロ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。個人紹介主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしど...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5