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

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() を使用するので、 クラス名として指定できるのは 英数字とハイフン ('-')、アンダースコア ('_') そしてピリオド ('.') だけです。

Loading Classes from PHP Namespaces

Starting in version 1.10.0, Zend Framework now allows loading classes from PHP namespaces. This support follows the same guidelines and implementation as that found in the PHP Framework Interop Group PSR-0 reference implementation.

Under this guideline, the following rules apply:

- Each namespace separator is converted to a `DIRECTORY_SEPARATOR` when loading from the file system.

- Each "_" character in the CLASS NAME is converted to a `DIRECTORY_SEPARATOR`. The "_" character has no special meaning in the namespace.

- The fully-qualified namespace and class is suffixed with ".php" when loading from the file system.

As examples:

- \Doctrine\Common\IsolatedClassLoader => `/path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php`

- \namespace\package\Class_Name => `/path/to/project/lib/vendor/namespace/package/Class/Name.php`

- \namespace\package_name\Class_Name => `/path/to/project/lib/vendor/namespace/package_name/Class/Name.php`

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

静的メソッド 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 スタックから削除されます。