PHPのオートロード

PHPでは、一般的に1つのクラス定義に対して、1つのPHPファイルを作成します。オブジェクト指向でプログラミングすると様々なクラスファイルを作成することになりますが、その都度requireやincludeで読み込むのは非常に手間がかかります。そこで、これを解決する手段として、PHPではオートロードという仕組みが用意されています。

__autoload()関数

__autoload()関数をグローバルに定義することにより、現在のファイルに定義されていないクラスを使おうとした際に自動的に__autoload()関数が呼ばれます。引数としてクラス名が渡されるので、__autoload()関数内の処理で対応するクラスファイルを読み込むことができます。

下記の例では、Fooクラスのインスタンスを作成しようとしていますが、未定義のため__autoload()関数に’Foo’が引数として渡されます。__autoload()関数の処理で、Foo.phpが読み込み可能であれば、読み込むようにしています。Foo.php内にFooクラスが定義されていれば、無事インスタンスを作成することができます。

PHP

<?php
function __autoload($name)
{
  echo '__autoload(' . $name . ') was called.', PHP_EOL;
  $file = $name . '.php';
  if (is_readable($file)) {
    require_once $file;
  }
}
$foo = new Foo();
?>

しかし、__autoload()関数はグローバルに定義するため、1度しか定義することができず、また処理を1つしか登録することができません。spl_autoload_register()関数を使えば、より柔軟にクラスのオートロードに対応できます。

spl_autoload_register()関数

spl_autoload_register()関数では、オートロードの処理をコールバック関数として複数登録することができます。現在のファイルに定義されていないクラスを使おうとした際に、登録されたコールバック関数をクラスが定義されるまで順番に呼び出します。それでもクラス定義が見つからなければ、最終的にFatal errorが発生します。

注意点として、spl_autoload_register()関数を使用するとグローバルの__autoload()関数は自動では呼ばれなくなるので、spl_autoload_register()関数で登録する必要があります。下記の例では、3番目に登録したBarクラスのload()メソッドでクラスファイルを読み込んでいるので、最後に登録したload()関数は呼ばれていないことがわかります。

PHP

<?php
function __autoload($name)
{
  echo '__autoload(' . $name . ') was called.', PHP_EOL;
}
class Hoge
{
  public static function load($name)
  {
    echo 'Hoge::load(' . $name . ') was called.', PHP_EOL;
  }
}
class Bar
{
  public function load($name)
  {
    echo '$bar->load(' . $name . ') was called.', PHP_EOL;
    $file = $name . '.php';
    if (is_readable($file)) {
      require_once $file;
    }
  }
}
function load($name)
{
  echo 'load(' . $name . ') was called.', PHP_EOL;
}
spl_autoload_register('__autoload');
spl_autoload_register('Hoge::load');
$bar = new Bar();
spl_autoload_register(array($bar, 'load'));
spl_autoload_register('load');
$foo = new Foo();
/* 出力:
__autoload(Foo) was called.
Hoge::load(Foo) was called.
$bar->load(Foo) was called.
*/
?>