LoginSignup
176
180

More than 5 years have passed since last update.

PHP で、spl_autoload_register を使って、require_once 地獄を脱出しよう

Last updated at Posted at 2013-10-08

目的

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';
176
180
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
176
180