SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

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

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

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

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

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

 コンテキストとは多少なじみがない方もいるのではないでしょうか。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のプログラムを変更することなく実装できるケースもあります。

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

参考資料

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
PHPエクステンションの作り方連載記事一覧

もっと読む

この記事の著者

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

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

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

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/7576 2014/01/21 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング