Commit 6ae715ff by Qiang Xue

refactored autoloading.

parent f2027c1c
...@@ -47,7 +47,8 @@ class YiiBase ...@@ -47,7 +47,8 @@ class YiiBase
/** /**
* @var array class map used by the Yii autoloading mechanism. * @var array class map used by the Yii autoloading mechanism.
* The array keys are the class names (without leading backslashes), and the array values * The array keys are the class names (without leading backslashes), and the array values
* are the corresponding class file paths. This property mainly affects how [[autoload()]] works. * are the corresponding class file paths (or path aliases). This property mainly affects
* how [[autoload()]] works.
* @see import * @see import
* @see autoload * @see autoload
*/ */
...@@ -188,10 +189,10 @@ class YiiBase ...@@ -188,10 +189,10 @@ class YiiBase
* it will be returned back without change. * it will be returned back without change.
* *
* Note, this method does not ensure the existence of the resulting path. * Note, this method does not ensure the existence of the resulting path.
* @param string $alias alias * @param string $alias the alias to be translated.
* @param boolean $throwException whether to throw an exception if the given alias is invalid. * @param boolean $throwException whether to throw an exception if the given alias is invalid.
* If this is false and an invalid alias is given, false will be returned by this method. * If this is false and an invalid alias is given, false will be returned by this method.
* @return string|boolean path corresponding to the alias, false if the root alias is not previously registered. * @return string|boolean the path corresponding to the alias, false if the root alias is not previously registered.
* @throws InvalidParamException if the alias is invalid while $throwException is true. * @throws InvalidParamException if the alias is invalid while $throwException is true.
* @see setAlias * @see setAlias
*/ */
...@@ -225,13 +226,14 @@ class YiiBase ...@@ -225,13 +226,14 @@ class YiiBase
* Note that this method neither checks the existence of the path nor normalizes the path. * Note that this method neither checks the existence of the path nor normalizes the path.
* Any trailing '/' and '\' characters in the path will be trimmed. * Any trailing '/' and '\' characters in the path will be trimmed.
* *
* @param string $alias alias to the path. The alias must start with '@'. * @param string $alias the alias name (e.g. "@yii"). It should start with a '@' character
* and should NOT contain the forward slash "/" or the backward slash "\".
* @param string $path the path corresponding to the alias. This can be * @param string $path the path corresponding to the alias. This can be
* *
* - a directory or a file path (e.g. `/tmp`, `/tmp/main.txt`) * - a directory or a file path (e.g. `/tmp`, `/tmp/main.txt`)
* - a URL (e.g. `http://www.yiiframework.com`) * - a URL (e.g. `http://www.yiiframework.com`)
* - a path alias (e.g. `@yii/base`). In this case, the path alias will be converted into the * - a path alias (e.g. `@yii/base`). In this case, the path alias will be converted into the
* actual path first by calling [[getAlias]]. * actual path first by calling [[getAlias()]].
* *
* @throws Exception if $path is an invalid alias * @throws Exception if $path is an invalid alias
* @see getAlias * @see getAlias
...@@ -268,50 +270,35 @@ class YiiBase ...@@ -268,50 +270,35 @@ class YiiBase
*/ */
public static function autoload($className) public static function autoload($className)
{ {
if (isset(self::$classMap[$className])) { $className = ltrim($className, '\\');
include(self::$classMap[$className]);
return true;
}
if (strrpos($className, '\\') > 0) { if (isset(self::$classMap[$className])) {
// namespaced class, e.g. yii\base\Component $classFile = self::$classMap[$className];
// convert namespace to path alias, e.g. yii\base\Component to @yii/base/Component } else {
$alias = '@' . str_replace('\\', '/', ltrim($className, '\\')); if (($pos = strrpos($className, '\\')) !== false) {
if (($path = static::getAlias($alias, false)) !== false) { // namespaced class, e.g. yii\base\Component
$classFile = $path . '.php'; $classFile = str_replace('\\', '/', substr($className, 0, $pos + 1))
} . str_replace('_', '/', substr($className, $pos + 1)) . '.php';
} elseif (($pos = strpos($className, '_')) !== false) { } else {
// PEAR-styled class, e.g. PHPUnit_Framework_TestCase $classFile = str_replace('_', '/', $className) . '.php';
// convert class name to path alias, e.g. PHPUnit_Framework_TestCase to @PHPUnit/Framework/TestCase
$alias = '@' . str_replace('_', '/', $className);
if (($path = static::getAlias($alias, false)) !== false) {
$classFile = $path . '.php';
} }
} if (strpos($classFile, '/') !== false) {
// make it into a path alias
if (!isset($classFile)) { $classFile = '@' . $classFile;
// search in include paths
foreach (self::$classPath as $path) {
$path .= DIRECTORY_SEPARATOR . $className . '.php';
if (is_file($path)) {
$classFile = $path;
$alias = $className;
break;
}
} }
} }
if (isset($classFile, $alias) && is_file($classFile)) { $classFile = static::getAlias($classFile);
if (basename(realpath($classFile)) === basename($alias) . '.php') { if ($classFile !== false && is_file($classFile)) {
include($classFile); include($classFile);
if (class_exists($className, false)) { if (class_exists($className, false) || interface_exists($className, false)) {
return true; return true;
} } else {
throw new Exception("Unable to find '$className' in file: $classFile");
} }
throw new Exception("The class file name '" . realpath($classFile) . "' does not match the class name '$className'. Please check the case of the names and make sure the class file does not have syntax errors."); } else {
return false;
} }
return false;
} }
/** /**
......
...@@ -121,7 +121,7 @@ class Application extends Module ...@@ -121,7 +121,7 @@ class Application extends Module
$this->registerErrorHandlers(); $this->registerErrorHandlers();
$this->registerCoreComponents(); $this->registerCoreComponents();
parent::__construct($config); Component::__construct($config);
} }
/** /**
......
...@@ -605,21 +605,14 @@ abstract class Module extends Component ...@@ -605,21 +605,14 @@ abstract class Module extends Component
$controller = Yii::createObject($this->controllerMap[$id], $id, $this); $controller = Yii::createObject($this->controllerMap[$id], $id, $this);
} elseif (preg_match('/^[a-z0-9\\-_]+$/', $id)) { } elseif (preg_match('/^[a-z0-9\\-_]+$/', $id)) {
$className = StringHelper::id2camel($id) . 'Controller'; $className = StringHelper::id2camel($id) . 'Controller';
$classFile = $this->controllerPath . DIRECTORY_SEPARATOR . $className . '.php'; $classFile = $this->controllerPath . DIRECTORY_SEPARATOR . $className . '.php';
if (is_file($classFile)) { $className = ltrim($this->controllerNamespace . '\\' . $className, '\\');
$className = $this->controllerNamespace . '\\' . $className; Yii::$classMap[$className] = $classFile;
if (!class_exists($className, false)) { if (class_exists($className)) {
require($classFile); if (is_subclass_of($className, 'yii\base\Controller')) {
}
if (class_exists($className, false) && is_subclass_of($className, '\yii\base\Controller')) {
$controller = new $className($id, $this); $controller = new $className($id, $this);
} elseif (YII_DEBUG) { } elseif (YII_DEBUG && !is_subclass_of($className, 'yii\base\Controller')) {
if (!class_exists($className, false)) { throw new InvalidConfigException("Controller class must extend from \\yii\\base\\Controller.");
throw new InvalidConfigException("Class file name does not match class name: $className.");
} elseif (!is_subclass_of($className, '\yii\base\Controller')) {
throw new InvalidConfigException("Controller class must extend from \\yii\\base\\Controller.");
}
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment