autoload and multiple directories

前端 未结 6 1614
醉酒成梦
醉酒成梦 2020-12-14 21:36

I\'ve just been looking at php\'s autoload() function. Seems a nice idea, but I\'m not sure how it handles multiple directories. My current development basically has a libra

6条回答
  •  -上瘾入骨i
    2020-12-14 21:51

    Here is a class I wrote a while ago for a similar purpose. That time I was still in the learning phase, so there might be stupid ideas involved; it worked nevertheless.

    The basic idea is that it scans the source directory once, and creates an array mapping classes to their source files. The class is registered as an autoloader, and when invoked, it includes the required file. If not found, it tries to rebuild the array on the fly.

    /* register ClassLoader as class loader */
    spl_autoload_register(array(ClassLoader::getInstance(), 'loadClass'));
    
    
    class ClassLoader {
    
        private static $SAVE_FILE = 'ClassLoader.save.php';
    
        /* singleton */
        private static $instance;
    
        /* stores a className -> filePath map */
        private $classList;
        /* tells whether working from saved file */
        private $refreshed;
    
    
        public static function getInstance() {
            if (!isset(self::$instance)) {
                self::$instance = new ClassLoader();
            }
            return self::$instance;
        }
    
        private function __construct() {
            $this->initClassList();
        }
    
        public function loadClass($className) {
            if ( !array_key_exists($className, $this->classList) && !$this->refreshed ) {
                $this->refreshClassList();
            }
            require_once($this->classList[$className]);
        }
    
        private function initClassList() {
            if (file_exists(INCLUDES_DIR . self::$SAVE_FILE)) {
                require_once(INCLUDES_DIR . self::$SAVE_FILE);
                $this->refreshed = FALSE;
            } else {
                $this->refreshClassList();
            } 
        }
    
        private function refreshClassList() {
            $this->classList = $this->scanDirectory(INCLUDES_DIR);
            $this->refreshed = TRUE;
    
            $this->saveClassList();
        }
    
        private function saveClassList() {
            $handle = fopen(INCLUDES_DIR . self::$SAVE_FILE, 'w');
            fwrite($handle, "classList as $class => $path) {
                $line = '$this->classList' . "['" . $class . "'] = '" . $path . "';\r\n";
                fwrite($handle, $line);
            }
    
            fwrite($handle, '?>');
            fclose($handle);
        }
    
        private function scanDirectory ($directory) {
            // strip closing '/'
            if (substr($directory, -1) == '/') {
                $directory = substr($directory, 0, -1);
            }
    
            if (!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) {
                return array();
            }
    
            $dirH = opendir($directory);
            $scanRes = array();
    
            while(($file = readdir($dirH)) !== FALSE) {
    
                // skip pointers
                if ( strcmp($file , '.') == 0 || strcmp($file , '..') == 0) {
                    continue;
                }
    
                $path = $directory . '/' . $file;
    
                if (!is_readable($path)) {
                    continue;
                }
    
                // recursion
                if (is_dir($path)) {
                    $scanRes = array_merge($scanRes, $this->scanDirectory($path));
    
                } elseif (is_file($path)) {
                    $className = explode('.', $file);
                    if ( strcmp($className[1], 'class') == 0 && strcmp($className[2], 'php') == 0 ) {
                        $scanRes[$className[0]] = $path; 
                    }
                }
            }
    
            return $scanRes;
        }
    
    }
    

提交回复
热议问题