目的
require_once
地獄を脱出したい!
require_once
は、実行順に依存するため、たとえば PHPUnit で起こらなかったのに、ブラウザで実行したらクラスがないよと怒られたり、ということがありえます。
spl_autoload_register()
とは
通常、
$user = new User();
などとして、そのクラスがない場合、
Fatal error: Class 'User' not found in ...
などとエラーになります。
その際、 spl_autoload_register()
を使ってメソッドを登録しておけば、エラーが出る前に、そのクラス定義を探す最後の救済メソッドを実行できます。
それでも見つからなければおなじみのエラーが出ます。
PHPのバージョンは?
- PHP 5.0.x の方
-
spl_autoload_register()
はありません。代わりに__autoload()
が使えますが、そんな開発やる前に転職しましょう。__autoload()
のことなど忘れてしまえ。
- PHP 5.1.2 以上の方
-
spl_autoload_register()
はサポートされていますが、オレオレフレームワークであっても、 このようなクラスは自作せず、 Composer のautoload などを利用することを考えましょう。 - また、PHPのサポート期限はバージョン毎に定められています。特にセキュリティ上の観点から、サポート中のバージョンを利用しましょう。 -> http://php.net/supported-versions.php
モダンPHPer へのさらなる利点
PHP5.3以上ですと、
- 名前空間が利用できる
- オートロード関数内で起きた例外もキャッチできる
- 無名関数を登録することも出来る
- 第2引数 prepare を使うことにより、オートロード関数を読み込む順番を制御できる。
お得ですね。
実装例
それでもオレオレ規約でクラスたちを管理したい方用の、実装例が以下になります。
ClassLoader.php
<?php
/**
* Classが定義されていない場合に、ファイルを探すクラス
*/
class ClassLoader
{
// class ファイルがあるディレクトリのリスト
private static $dirs;
/**
* クラスが見つからなかった場合呼び出されるメソッド
* spl_autoload_register でこのメソッドを登録してください
* @param string $class 名前空間など含んだクラス名
* @return bool 成功すればtrue
*/
public static function loadClass($class)
{
foreach (self::directories() as $directory) {
// 名前空間や疑似名前空間をここでパースして
// 適切なファイルパスにしてください
$file_name = "{$directory}/{$class}.php";
if (is_file($file_name)) {
require $file_name;
return true;
}
}
}
/**
* ディレクトリリスト
* @return array フルパスのリスト
*/
private static function directories()
{
if (empty(self::$dirs)) {
$base = '/path/to/application/dir';
self::$dirs = array(
// ここに読み込んでほしいディレクトリを足していきます
$base . '/controllers',
$base . '/models'
);
}
return self::$dirs;
}
}
// これを実行しないとオートローダーとして動かない
spl_autoload_register(array('ClassLoader', 'loadClass'));
使い方
さあ、今まで書いた require_once
とサヨナラです。
require_once '/path/to/ClassLoader.php';