diff --git a/base.php b/base.php index 00d3c340..b1e1b373 100644 --- a/base.php +++ b/base.php @@ -32,6 +32,7 @@ defined('CONF_EXT') or define('CONF_EXT', EXT); // 配置文件后缀 defined('ENV_PREFIX') or define('ENV_PREFIX', 'PHP_'); // 环境变量的配置前缀 defined('IS_API') or define('IS_API', false); // 是否API接口 defined('APP_AUTO_RUN') or define('APP_AUTO_RUN', true); // 是否自动运行 +defined('AUTO_SCAN_PACKAGE') or define('AUTO_SCAN_PACKAGE', false); // 是否自动扫描非Composer安装类库 // 环境常量 define('IS_CLI', PHP_SAPI == 'cli' ? true : false); diff --git a/library/think/Loader.php b/library/think/Loader.php index eaa2a7fb..b7b23cdb 100644 --- a/library/think/Loader.php +++ b/library/think/Loader.php @@ -12,7 +12,6 @@ namespace think; use think\App; -use think\exception\HttpException; use think\exception\ClassNotFoundException; use think\Request; @@ -60,16 +59,27 @@ class Loader if (!strpos($class, '\\')) { return false; } + // 解析命名空间 list($name, $class) = explode('\\', $class, 2); if (isset(self::$namespace[$name])) { - // 注册的命名空间 + // 根命名空间 $path = self::$namespace[$name]; } elseif (is_dir(EXTEND_PATH . $name)) { // 扩展类库命名空间 $path = EXTEND_PATH . $name . DS; } else { - return false; + // 非根命名空间检测 + foreach (self::$namespace as $ns => $val) { + if (strpos($ns, '\\') && 0 === strpos($name . '\\' . $class, $ns)) { + $path = $val; + $class = substr($name . $class, strlen($ns)); + break; + } + } + if (!isset($path)) { + return false; + } } $filename = $path . str_replace('\\', DS, $class) . EXT; if (is_file($filename)) { @@ -120,20 +130,80 @@ class Loader { // 注册系统自动加载 spl_autoload_register($autoload ?: 'think\\Loader::autoload'); - + if (is_dir(VENDOR_PATH . 'composer')) { // 注册Composer自动加载 self::registerComposerLoader(); - self::$composerLoader = true; - } elseif(is_file(VENDOR_PATH . 'think_autoload.php')) { + self::$composerLoader = true; + } elseif (is_file(VENDOR_PATH . 'think_autoload.php')) { // 读取Composer自动加载文件 $autoload = include VENDOR_PATH . 'think_autoload.php'; if (is_array($autoload)) { self::addMap($autoload); } + } elseif (AUTO_SCAN_PACKAGE) { + if (is_file(RUNTIME_PATH . 'class_namespace.php')) { + self::addNamespace(include RUNTIME_PATH . 'class_namespace.php'); + if (is_file(RUNTIME_PATH . 'load_files.php')) { + $files = include RUNTIME_PATH . 'load_files.php'; + foreach ($files as $file) { + include $file; + } + } + } else { + // 自动扫描下载Composer安装类库 + $dirs = scandir(VENDOR_PATH, 1); + $namespace = []; + foreach ($dirs as $dir) { + if ('.' != $dir && '..' != $dir && is_file(VENDOR_PATH . $dir . DS . 'composer.json')) { + // 解析 package的composer.json 文件 + $namespace = array_merge($namespace, self::parseComposerPackage(VENDOR_PATH . $dir . DS)); + } + } + if (!empty($namespace)) { + self::addNamespace($namespace); + // 生成缓存 + file_put_contents(RUNTIME_PATH . 'class_namespace.php', " $path) { + $namespace[rtrim($ns, '\\')] = realpath($package . $path . DS . str_replace('\\', DS, $ns)) . DS; + } + } + + if (isset($autoload['psr-4'])) { + foreach ($autoload['psr-4'] as $ns => $path) { + $namespace[rtrim($ns, '\\')] = realpath($package . $path) . DS; + } + } + + if (isset($autoload['files'])) { + foreach ($autoload['files'] as $file) { + self::$load[] = realpath($package . $file); + require $package . $file; + } + } + } + return $namespace; + } + // 注册composer自动加载 private static function registerComposerLoader() {