外部PHPファイルをインポートして呼び出そうとするとき、いちいちファイルの頭で読み込む数だけincludeを行うのは面倒くさいですね。それならば、使いそうなクラス・関数をfunctions.phpのような一ファイルにまとめてしまえば呼び出しが一回で済む、ということも考えつきますが、これだと一クラス一ファイルの原則に反する上、外部ライブラリを使用する場合などは結局インクルードが必要になり、上手く行きません。
そこで、PHP5以降のヴァージョンに搭載された便利なautoload機能を使いましょう。
PHP5以降の__autoload関数を使ったautoload
PHPには、マジックメソッドと呼ばれる”__(アンダーバー2つ)”から始まる特殊なメソッドがあります。たとえばPHPのクラスについてのエントリで出てきた、__construct。これは予約されたメソッド名なので、この名前を使ってオリジナルの関数を作ってはいけません。既にこの名前のメソッドには使用方法が決められているのです。__constructであれば、クラスのインスタンスが作られたときに呼び出される処理ということでしたね。
さて、autoload機能を実現する__autoloadは、クラスに紐づけられたメソッドというわけではなく、グローバル関数です。ですが、基本的にはマジックメソッドの一類であると考えて下さい。この関数は、未定義のクラスが呼ばれた際に自動的に呼び出されます。
<?php //未定義のクラス $instance = new undefinedClass(); ?> |
もしこの呼び出しの時点で、undefinedClass.phpをincludeしていなかったら、通常はメソッドが見つからないというエラーになります。一方、__autoloadを定義しておくことで、こうしたクラスの見つからないケースでの挙動を指定できます。
<?php __autoload($classname){ include $classname . ".php"; } ?> |
__autoloadは呼び出されたクラス名を引数としてとるので、それを適当な変数名で受けて、includeするファイルネームを生成する処理を書くのです。こうすることによって、クラスを作ったらクラス名.phpという名前に保存するようにすれば、呼び出し時に自動的に探し出してincludeしてくれます。
PHP5.1.2以降のspl_autoload_register関数を使ったautoload
ただ、__autoloadにも不便な点があります。それは、一度定義してしまうと、それ以外の__autoload処理を追加していくことが出来ないということです。__constructの例と同じように、こうした特別なメソッドは一度きりのタイミングに処理を登録することが許されているのです。そこで、複数のautoload処理(たとえば、優先順をつけて探索処理を追加したい場合)を登録するにはどうすれば良いか。そのような場合には、spl_autoload_register関数で処理を追加します。
//autoloadスタックに登録したい関数その1 function searchClassPhp($classname){ include $classname . ".class.php"; } //autoloadスタックに登録したい関数その2 function searchPhp($classname){ include $classname . ".php"; } //関数を両方ともautoloadスタックに追加 spl_autoload_register("searchClassPhp"); spl_autoload_register("searchPhp"); |
この例では、定義されていないundefinedClassが呼ばれたとき、最初にundefinedClass.class.phpというファイルが存在するかチェックされます。もし見つからない場合は、undefinedClass.phpが探されます。
ちなみに、spl_autoload_register関数を使ってしまうと、__autoloadで定義した処理は魔法が解けて無視されるようになってしまいます。そこで、__autoloadを定義しており、spl_autoload_register関数も使いたい場合には、__autoload自体もautoloadスタックに登録して下さい。
//魔法の解けた__autoloadを普通の関数として登録 spl_autoload_register("__autoload"); |
spl_autoload_register関数には、無名関数も登録することが出来ます。
//無名関数の登録 spl_autoload_register(function($classname){ include $classname . ".class.php"; }); |
ただし無名関数については5.3.0以降のヴァージョンに限定されます。だんだん便利になっているのか、母屋を継ぎ足し継ぎ足し増築しているのか、なんともPHPらしいですね。