注意: この章の残りの部分に進む前に、お好みの Web サーバの (変更されていない) ソースを取得しておきましょう。ここでは、Apache (http://www.apache.org/ で取得できます) を使用します。また、もちろん PHP のソース (http://www.php.net/ にあります - 言うまでもないですよね?) も必要です。
PHP の動作環境を自分でコンパイルして作成できるようにしておいて ください! この方法についてはここでは触れませんが、この章の内容を 学習しようとするのなら、最低限知っておくべき基本的な内容です。
コードの内容について説明する前に、PHP のファイルを探索する助けになるよう ソースツリーの内容に慣れておくべきです。これは、拡張モジュールを 開発したりデバッグしたりする際の必須技能です。
以下の表では、主なディレクトリの内容について説明しています。
ディレクトリ | 内容 |
php-src | PHP 本体のソースファイルおよびヘッダファイル。 PHP の API 定義やマクロなどはここにあります (重要)。 それ以外のものは、このディレクトリの下位階層にあります。 |
php-src/ext | 動的モジュール、組み込みモジュールのソース置き場。 デフォルトでは、PHP 本体のソースツリーに統合された「公式」 モジュールが配置されています。PHP 4.0 以降、これらの標準 拡張モジュールを (そのモジュールがサポートしていれば) 動的モジュールとしてコンパイルすることが可能となりました。 |
php-src/main | このディレクトリには PHP 本体のマクロや定義があります (重要)。 |
php-src/pear | PHP Extension and Application Repository (PEAR) のディレクトリです。 ここには PEAR のコアファイルが含まれます。 |
php-src/sapi | さまざまなサーバ用の抽象化レイヤのコードを含みます。 |
TSRM | Zend および PHP の "Thread Safe Resource Manager" (TSRM) の場所です。 |
ZendEngine2 | Zend エンジンのファイルがあります。この中で、Zend の API 定義やマクロなどのすべてが見つけられるでしょう (重要)。 |
PHP パッケージに含まれるすべてのファイルについて取り上げることは この章の範囲を超えています。しかし、以下のファイルについては 詳しく見ておくべきでしょう。
PHP の main ディレクトリにある php-src/main/php.h。 このファイルには PHP のマクロおよび API 定義の大半が含まれています。
Zend ディレクトリにある php-src/Zend/zend.h。 このファイルには Zend のマクロおよび定義の大半が含まれています。
これもまた Zend ディレクトリにある php-src/Zend/zend_API.h。 ここでは Zend の API を定義しています。
Zend は、ある規約に基づいて構築されています。 この標準規約を破ることを避けるため、 以下の節で説明する規則を守らなければなりません。
重要なタスクのほぼ全てについて、Zend では便利なマクロを定義しています。 以下の表および図で、基本的な関数・構造体およびマクロについて 説明しています。マクロ定義のほとんどは zend.h あるいは zend_API.h にあります。この章を勉強したあとで、 これらのファイルをじっくり読んでみることをお勧めします (もちろん今この場で読んでもよいのですが、 まだこの段階ではすべてを理解することはできないでしょう)。
特にサーバソフトウェアにとって、リソース管理は重大な問題です。 メモリは最も貴重なリソースのひとつなので、 メモリ管理には最大限の注意を払わねばなりません。 メモリ管理の一部は Zend によって抽象化されており、 この抽象化を使用すべきなのは明白です。この抽象化を使用することにより、 Zend はすべてのメモリ割り当てを完全に制御できるようになります。 そのブロックが使用中なのかどうかを Zend が判断し、 未使用のブロックや参照されていないブロックを自動的に開放することで メモリリークを防ぐことができます。 このために使用する関数を、以下の表にまとめます。
関数 | 説明 |
emalloc() | malloc() の代わりに使用します。 |
efree() | free() の代わりに使用します。 |
estrdup() | strdup() の代わりに使用します。 |
estrndup() | strndup() の代わりに使用します。 estrdup() より高速で、バイナリセーフです。 複製する文字列の長さが事前にわかっている場合には、 この関数を使用することを推奨します。 |
ecalloc() | calloc() の代わりに使用します。 |
erealloc() | realloc() の代わりに使用します。 |
警告 |
スクリプトの終了後も残り続けるメモリを確保するために、 malloc() および free() を使用することも可能です。しかし、これらの関数を使用するのは Zend API がどうしてもそれを要求している場合に限定し、 最大限の注意を払うようにしてください。それ以外の場合に使用すると、 メモリリークが発生する恐れがあります。 |
Zend モジュール内では、以下のディレクトリ関数およびファイル関数を使用しなければなりません。 これらの関数の機能はそれぞれ対応する C 関数と同じですが、 さらにスレッドレベルでの仮想実行ディレクトリがサポートされています。
Zend エンジンでは、文字列はその他の値 (整数値、論理値など) と少し異なる方法で処理されます。 これらの値を保存するために、追加のメモリを確保する必要はありません。 関数から文字列を返したい場合は、新しい文字列変数を シンボルテーブルかそれに類似のものに登録します。 その文字列が使用するメモリは、先ほど説明した e*() 関数で事前に確保しておかなければなりません (この段階では、まだあまりピンとこないかもしれません。 とりあえずは頭の片隅に置いておいてください。あとでもう一度説明します)。
配列やオブジェクトのような複雑な型については、扱いかたが異なります。 Zend はこれらの型を扱うための API を提供しており、 これらの型はハッシュテーブルとして保存されます。
注意: これ以降のサンプルソースでは、 読みやすさを考慮して integer などの単純な型のみを使用します。 より高度な型を作成する方法については、この章の後半で説明します。