CodeZine(コードジン)

特集ページ一覧

PHPで外部ライブラリ(libzip)を組み込んで利用する

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

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

クラスのインスタンスを返す方法と引数として利用する方法

 続いて、クラスのインスタンスを返す方法や、引数として利用する方法を紹介します。クラスのインスタンスを返すことで、配列と同様に一度に多くのデータを戻すことができ、また配列とは違い、よりデータへのアクセス方法が管理されたデータをPHP側に戻すことができます。そして、引数にクラスのインスタンスを使えば、プリミティブな値と違ってPHPエンジニア側のタイプミスなどが起こりにくくなります。クラス構成でエクステンションを作成する場合には、ぜひ利用したいテクニックの一つです。

メソッドの中でクラスのインスタンスを返す

 PZipEntryクラスのインスタンスを返すメソッドを実装します。実際に実行される時のPHPのコードは、以下のようになります。

PHP側のコード:クラスのインスタンスを返すメソッド
$entry = $pzip_file->getEntry(0);

 また、クラスのインスタンスを返すエクステンション側の実装は以下のようになります。

クラスのインスタンスを返す(pzip_file.cの抜粋)
PHP_METHOD(PZipFile, getEntry){
    : // (省略)
    php_pzip_entry *entry;
    : // (省略)
    else{
        : // (省略)
        object_init_ex(return_value, pzip_entry_ce); // ……(1)
        
        Z_SET_REFCOUNT_P(return_value, 1);           // ……(2)
        Z_SET_ISREF_P(return_value);                 // ……(3)
        entry = (php_pzip_entry *)zend_object_store_get_object(return_value TSRMLS_CC); //……(4)
        entry->stat = stat;                          // ……(5)
    }
}

 (1)でPZipEntryのzend_class_entryである、pzip_entry_ceを指定し、インスタンスを初期化します。(2)(3)はインスタンスの参照カウンタを設定します。参照カウンタについては、http://www.php.net/manual/ja/features.gc.refcounting-basics.phpを参照すると詳しいことが分かります。(4)zend_object_store_get_objectでreturn_valueの変数から、クラスの内部データを管理するphp_pzip_entryの構造体を取得します。(5)では、その構造体に値を設定していきます。同様にほかの変数に値を設定することも可能です。

クラスのインスタンスを引数として利用する

 クラスのインスタンスを引数から取得するには、ほかと同様にzend_parse_parameters()を利用すればよいので、非常に簡単に取得できます。

クラスのインスタンスを引数から取得(pzip_file.cの抜粋)
PHP_METHOD(PZipFile, getStream){
    : // (省略)
    zval *z_entry;
    php_pzip_entry *entry;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O",
                          &z_entry, pzip_entry_ce) == FAILURE ){  // ……(1)
        return;
    }
    entry = (php_pzip_entry *)zend_object_store_get_object(z_entry TSRMLS_CC); // ……(2)
    : // (省略)
    if(entry->stat->encryption_method){                           // ……(3)
        if(!obj->password){
            php_error_docref(NULL TSRMLS_CC, E_ERROR, "Please set password");
            RETURN_FALSE;
        }
        zf = zip_fopen_index_encrypted(obj->zip,entry->stat->index,flags,obj->password);   // ……(4)
    }
    else{
        zf = zip_fopen_index(obj->zip,entry->stat->index,flags);  // ……(5)
    }
    : // (省略)
}

 (1)zend_parse_parameters()の第1引数に"O"を指定し、第2引数には実際に値が設定されるzvalの変数、第3引数にはクラスの型を示すzend_class_entryの型であるpzip_entry_ce変数を設定します。そして、そのクラスの内部データ構造体の変数を取得するには、(2)zend_object_store_get_object()を利用します。このとき、引数として(1)で取得したzvalの値を引数に設定します。これで構造体にアクセスできたので、後はそれぞれの実装をしていくことが可能です。

 今回のサンプルでは、(3)のようにZIPのエントリーから暗号方式の情報を取得し、その状況に合わせて、(4)暗号解読方式でのZIPエントリデータのオープン、もしくは、(5)通常法方式でのZIPエントリデータのオープンをしています。

 以上でクラスのひな形としての実装は終了しました。ただし、実際にzip_fopen_index関数を通じて取得したリソースは、まだ扱うことができません。次回はそのリソースをPHPでのストリーム関数を通じてアクセスできるようにします。

最後に

 今回はlibzipというライブラリを組み込み、PHPで標準的に用意されているZipArchiveで足りない部分を補うことができるようにサンプルコードを紹介しました。実際のエクステンションの開発をゼロから行うことはなくても、既存のエクステンションに機能を追加することができれば、より利用シーンが広がると思います。

 また、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