# ファイルやクラスの動的な読み込み

`Zend_Loader` クラスは、ファイルを動的に読み込むためのメソッドを提供します。

## Zend_Loader 対 require_once()

`Zend_Loader` のメソッドは、読み込みたいファイルの名前が変化する場合に便利です。 たとえば、ユーザの入力やメソッドの引数などのパラメータに基づいたファイル名を使用する場合などです。 もし読み込むファイルやクラスの名前が決まっている場合は、 `require_once()` のような PHP の関数ではなくあえて `Zend_Loader` を使用するメリットはありません。

## ファイルの読み込み

静的メソッド `Zend_Loader::loadFile()` は、PHP ファイルを読み込みます。 読み込まれるファイルには任意の PHP コードを含めることができます。 このメソッドは PHP 関数 `include()` のラッパーで、失敗した場合 (たとえば指定したファイルが存在しないなど) には false を返します。

### loadFile() メソッドの例

    Zend_Loader::loadFile($filename, $dirs=null, $once=false);

引数 `$filename` には読み込むファイル名を指定します。 ここにはパス情報を含めてはいけません。`$filename` に対してはセキュリティチェックが行われます。 `$filename` に含めることができるのは英数字、ダッシュ ("-")、 アンダースコア ("_") あるいはピリオド (".") だけです。 引数 `$dirs` にはそのような制限はありません。

引数 `$dirs` にはファイルを探すディレクトリを指定します。 `NULL` の場合は `include_path` の中のみを対象とします。 文字列あるいは配列を指定すると、指定されたディレクトリをまず探した後で、 それから `include_path` を探します。

引数 `$once` は論理値です。`TRUE` を指定すると、 `Zend_Loader::loadFile()` は PHP の関数 `include_once()` でファイルを読み込みます。それ以外の場合は `include()` を使用します。

## クラスの読み込み

静的メソッド `Zend_Loader::loadClass($class, $dirs)` は、PHP ファイルを読み込んでクラスが存在するかどうかを確かめます。

### loadClass() メソッドの例

    Zend_Loader::loadClass('Container_Tree',
        array(
            '/home/production/mylib',
            '/home/production/myapp'
        )
    );

クラスを指定する文字列は、アンダースコアを OS のパス区切り文字に変換して最後に '.php' を追加したものとなります。上の例では、Windows 上で 'Container_Tree' は 'Container\\Tree.php' となります。

`$dirs` に文字列あるいは配列を指定すると、 `Zend_Loader::loadClass()` は指定した順にそのディレクトリを探します。 そして最初に見つかったファイルを読み込みます。 ディレクトリ `$dirs` にファイルがみつからない場合は、 PHP の `include_path` で指定された場所を探します。

ファイルが見つからない場合、あるいは読み込んだファイルにクラスが存在しない場合は `Zend_Loader::loadClass()` は `Zend_Exception` をスローします。

ファイルの読み込みには `Zend_Loader::loadFile()` を使用するので、 クラス名として指定できるのは 英数字とハイフン ('-')、アンダースコア ('_') そしてピリオド ('.') だけです。

## ファイルが読み込み可能かどうかの確認

静的メソッド `Zend_Loader::isReadable($pathname)` は、指定した場所にファイルが存在して読み込み可能な場合に `TRUE`、それ以外の場合に `FALSE` を返します。

### isReadable() メソッドの例

    if (Zend_Loader::isReadable($filename)) {
        // $filename で何かをします
    }

引数 `$filename` で、調べたいファイル名を指定します。 ここにはパス情報を含めることもできます。 このメソッドは、PHP の関数 `is_readable()` のラッパーです。この関数は `include_path` を探しませんが、`Zend_Loader::isReadable()` は `include_path` も検索対象に含めます。

## Autoloader の使用法

`Zend_Loader` クラスには、PHP の SPL 自動ローダーに登録するためのメソッドが含まれています。そのコールバックメソッドが `Zend_Loader::autoload()` です。利便性を考慮して、 `Zend_Loader` では `registerAutoload()` 関数を提供しています。 この関数は、`autoload()` メソッドを登録するものです。 `spl_autoload` 拡張モジュールが使用できない環境の場合は、 `registerAutoload()` メソッドは `Zend_Exception` をスローします。

### 自動ローダー用コールバックメソッドの登録例

    Zend_Loader::registerAutoload();

Zend Framework の autoload コールバックを登録すると、 明示的に読み込まなくても Zend Framework のクラスを参照できるようになります。 `autoload()` メソッドは、クラスを参照する際に自動的に `Zend_Loader::loadClass()` を使用します。

`Zend_Loader` クラスを継承した場合は、`registerAutoload()` に引数を追加することができます。この引数で、どのクラスから `autoload()` メソッドを登録するのかを指定します。

### autoload コールバックメソッドを継承クラスから登録する例

PHP における静的関数の参照の方法上、 `loadClass()` と `autoload()` の両方のコードを実装する必要があります。 そして、`autoload()` では `self::loadClass()` をコールしなければなりません。 作成する `autoload()` メソッドが親クラスに `self::loadClass()` の処理を任せるのなら、 サブクラスのメソッドではなく親クラス側の同名のメソッドをコールします。

    class My_Loader extends Zend_Loader
    {
        public static function loadClass($class, $dirs = null)
        {
            parent::loadClass($class, $dirs);
        }

        public static function autoload($class)
        {
            try {
                self::loadClass($class);
                return $class;
            } catch (Exception $e) {
                return false;
            }
        }
    }

    Zend_Loader::registerAutoload('My_Loader');

autoload コールバックを削除することもできます。 `registerAutoload()` にはオプションで 2 番目の引数を指定することができ、 デフォルトでは `TRUE` が設定されるようになっています。 この引数を `FALSE` とすると、 指定したコールバックが SPL の autoload スタックから削除されます。