[PHP] 自分で作るMVCフレームワーク【ClassLoader】

#### ClassLoader

new　された時点で
そのクラスが読み込まれていないクラスであれば
あらかじめ登録しておいたディレクトリ内を走査して、
自動的に読み込んでくれるモジュール。

[spl_autoload_register](http://fr2.php.net/manual/ja/function.spl-autoload-register.php) を使います。


```php:ClassLoader.class.php
<?php
/**
 * file doc comment
 *
 * PHP version 7
 *
 * @category Category
 * @package  Package
 * @author   hoge <hoge@example.com>
 * @license  http://opensource.org/licenses/MIT The MIT License (MIT)
 * @link     https://github.com/hoge/hoge
 */
/**
 * class doc comment
 *
 * PHP version 7
 *
 * @category Category
 * @package  Package
 * @author   hoge <hoge@example.com>
 * @license  http://opensource.org/licenses/MIT The MIT License (MIT)
 * @link     https://github.com/hoge/hoge */
final class ClassLoader
{
    private static $_files = [];


    /**
     * create instance guard
     *
     * @return void
     */
    final private function __construct(){}


    /**
     * アプリケーションディレクトリ以下のCLASS_FILEを探して登録する
     *
     * @return void
     */
    final public static function initialize()
    {
        if (! is_readable(SYS_ROOT)) {
            trigger_error('not found SYS_ROOT directory.['.SYS_ROOT.']');
            exit;
        }

        if (! is_readable(CORE)) {
            trigger_error('not found CORE directory.['.CORE.']');
            exit;
        }

        if (! is_readable(APP)) {
            trigger_error('not found APP directory.['.APP.']');
            exit ;
        }

        if (! defined('CLASS_FILE')) {
            trigger_error('you need to define CLASS_FILE.');
            exit ;
        }

        if (! defined('DS')) {
            define('DS', DIRECTORY_SEPARATOR);
        }

        if (! defined('SP')) {
            define('SP', "\x20");
        }

        if (isset($_SERVER['OS']) && preg_match('/^Windows/', $_SERVER['OS'])) {
            define('OS', 'win');
        } else {
            define('OS', 'linux');
        }

        switch (OS) {
        case 'win':
            // windowsで使うとき
            $_cmd = 'dir /S /B'.SP.SYS_ROOT.DS.'*'.CLASS_FILE;
            break;
        case 'linux':
            $_cmd = '/usr/bin/find'.SP.CORE.SP.APP.SP.'-name'.SP.'*'.CLASS_FILE;
            break;
        }

        exec($_cmd, $retArray, $retVal);
        array_walk($retArray, 'self::_register');
        spl_autoload_register('self::_loader');
    }


    /**
     * function doc comment
     *
     * @param string $_val description
     *
     * @return void
     */
    final private static function _register($_val='')
    {
        $_base = basename($_val);
        self::$_files[$_base] = [
            'dirname'  => dirname($_val),
            'basename' => $_base,
        ];
    }


    /**
     * function doc comment
     *
     * @param string $_class description
     *
     * @return void
     */
    final private static function _loader($_class='')
    {
        if (array_key_exists($_class.CLASS_FILE, self::$_files)) {
            $_array = self::$_files[$_class.CLASS_FILE];
            if (is_readable($_array['dirname'].DS.$_array['basename'])) {
                include_once $_array['dirname'].DS.$_array['basename'];
            }
        }
    }
}
```

ClassLoader 自身の読み込みは最初に行います。

```php:index.php
/**
 * Core Settings
 */
define('DS', DIRECTORY_SEPARATOR);

define('APP_NAME', 'SmapleProject');
define('VERSION',  'app');
define('ROOT',     DS.'var'.DS.'www');

/**
 * required by ClassLoader.class
 */
define('SP', "\x20");
define('SYS_ROOT', ROOT.DS.APP_NAME.DS.VERSION);
define('LIBS', SYS_ROOT.DS.'libs');
define('CORE', SYS_ROOT.DS.'core');
define('APP',  SYS_ROOT.DS.'app');
define('CLASS_FILE', '.class.php');

/**
 * Class Loader
 */
require_once CORE.DS.'ClassLoader'.CLASS_FILE;
$loader = ClassLoader::initialize();
```

かっこいい手段・方法がありましたら、ご教授ください。


#### 参考文献
+ [PHPのオブジェクト指向入門 | オブジェクト指向PHP.NET
](http://www.objective-php.net/mvc/index/)
+ [Zend Framework PHP 標準コーディング規約](http://framework.zend.com/manual/1.12/ja/coding-standard.html)
+ [PEAR 標準コーディング規約](http://pear.php.net/manual/ja/standards.php)
+ [PSR-2-coding-style-guide.md](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)