Yii 2.0.6 - 从入口到Action执行
Posted ~~逍遥~~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Yii 2.0.6 - 从入口到Action执行相关的知识,希望对你有一定的参考价值。
defined(‘YII_DEBUG‘) or define(‘YII_DEBUG‘, true); defined(‘YII_ENV‘) or define(‘YII_ENV‘, ‘dev‘); require(__DIR__ . ‘/../vendor/autoload.php‘); // 注册 Composer 加载器 Yii::setAlias(‘@common‘, dirname(__DIR__)); // 注册别名 { yiiBaseYii::setAlias($alias, $path) { if (strncmp($alias, ‘@‘, 1)) { $alias = ‘@‘ . $alias; } $pos = strpos($alias, ‘/‘); $root = $pos === false ? $alias : substr($alias, 0, $pos); if ($path !== null) { $path = strncmp($path, ‘@‘, 1) ? rtrim($path, ‘\/‘) : static::getAlias($path); if (!isset(static::$aliases[$root])) { if ($pos === false) { static::$aliases[$root] = $path; } else { static::$aliases[$root] = [$alias => $path]; } } elseif (is_string(static::$aliases[$root])) { if ($pos === false) { static::$aliases[$root] = $path; } else { static::$aliases[$root] = [ $alias => $path, $root => static::$aliases[$root], ]; } } else { static::$aliases[$root][$alias] = $path; krsort(static::$aliases[$root]); } } elseif (isset(static::$aliases[$root])) { if (is_array(static::$aliases[$root])) { unset(static::$aliases[$root][$alias]); } elseif ($pos === false) { unset(static::$aliases[$root]); } } } } require(__DIR__ . ‘/../vendor/yiisoft/yii2/Yii.php‘); { class Yii extends yiiBaseYii { } spl_autoload_register([‘Yii‘, ‘autoload‘], true, true); // 注册类加载器 yiiBaseYii::autoload($className) { if (isset(static::$classMap[$className])) { // 查找 $classMap 映射 $classFile = static::$classMap[$className]; if ($classFile[0] === ‘@‘) { $classFile = static::getAlias($classFile); } } elseif (strpos($className, ‘\‘) !== false) { $classFile = static::getAlias(‘@‘ . str_replace(‘\‘, ‘/‘, $className) . ‘.php‘, false); // 通过别名获取 { yiiBaseYii::getAlias($alias, $throwException = true) { if (strncmp($alias, ‘@‘, 1)) { // not an alias return $alias; } $pos = strpos($alias, ‘/‘); $root = $pos === false ? $alias : substr($alias, 0, $pos); if (isset(static::$aliases[$root])) { if (is_string(static::$aliases[$root])) { return $pos === false ? static::$aliases[$root] : static::$aliases[$root] . substr($alias, $pos); } foreach (static::$aliases[$root] as $name => $path) { if (strpos($alias . ‘/‘, $name . ‘/‘) === 0) { return $path . substr($alias, strlen($name)); } } } if ($throwException) { throw new InvalidParamException("Invalid path alias: $alias"); } return false; } } if ($classFile === false || !is_file($classFile)) { return; } } else { return; } include($classFile); // 加载类 if (YII_DEBUG && !class_exists($className, false) && !interface_exists($className, false) && !trait_exists($className, false)) { throw new UnknownClassException("Unable to find ‘$className‘ in file: $classFile. Namespace missing?"); } } Yii::$classMap = require(__DIR__ . ‘/classes.php‘); // 内置类 { return [ ‘yiiaseAction‘ => YII2_PATH . ‘/base/Action.php‘, ‘yiiaseActionEvent‘ => YII2_PATH . ‘/base/ActionEvent.php‘, ‘yiiaseActionFilter‘ => YII2_PATH . ‘/base/ActionFilter.php‘, ‘yiiaseApplication‘ => YII2_PATH . ‘/base/Application.php‘, ‘yiiaseArrayAccessTrait‘ => YII2_PATH . ‘/base/ArrayAccessTrait.php‘, ‘yiiaseArrayable‘ => YII2_PATH . ‘/base/Arrayable.php‘, ]; } Yii::$container = new yiidiContainer(); } $config = array( ‘id‘=>‘app-debugmodule‘, ‘basePath‘=>dirname(__DIR__), ‘controllerNamespace‘=>‘debugmodulecontrollers‘, ‘defaultRoute‘=>‘index/index‘, ‘params‘=>[ ‘adminEmail‘ => ‘[email protected]‘, ‘supportEmail‘ => ‘[email protected]‘, ‘user.passwordResetTokenExpire‘ => 3600, ], ‘components‘=>array_merge( [ ‘cache‘ => [ ‘class‘ => ‘yiicachingFileCache‘, ‘cachePath‘ => ‘@runtime/cache‘, ], ‘log‘ => [ ‘class‘ => ‘yiilogDispatcher‘, ‘traceLevel‘ => YII_DEBUG ? 3 : 0, ‘targets‘ => [ [ ‘class‘ => ‘yiilogFileTarget‘, ‘levels‘ => [‘error‘, ‘warning‘], ‘enabled‘ => true, ‘logFile‘=>‘@runtime/logs/app.log‘, ‘categories‘ => [], // 全部记录 ‘except‘ => [‘yiidb*‘], // 不记录的分类 ‘logVars‘ => [], // ‘logVars‘ => [‘_GET‘, ‘_POST‘, ‘_FILES‘, ‘_COOKIE‘, ‘_SESSION‘, ‘_SERVER‘], ], ], ], ‘mailer‘ => [ ‘class‘ => ‘yiiswiftmailerMailer‘, ‘transport‘ => array( // 发送到互联网的传输方法 ‘class‘=>‘Swift_Transport_MailTransport‘, ‘constructArgs‘=>array( array(‘class‘=>‘Swift_Transport_SimpleMailInvoker‘), array(‘class‘=>‘Swift_Events_SimpleEventDispatcher‘) ) ) ], ‘security‘ => [ ‘class‘ => ‘yiiaseSecurity‘ ], ‘i18n‘ => [ ‘class‘ => ‘yiii18nI18N‘, ‘translations‘=>[ ‘common‘=>[ // 语言转换器 ‘class‘ => ‘yiii18nPhpMessageSource‘, ‘basePath‘ => ‘@common/messages‘, ], ‘debugmodule‘=>[ ‘class‘ => ‘yiii18nPhpMessageSource‘, ‘basePath‘ => ‘@debugmodule/messages‘, ], ‘*‘=>[ // 默认语言转换器 ‘class‘ => ‘yiii18nPhpMessageSource‘, ‘basePath‘ => ‘@common/messages‘, ] ] ], // radis ‘redis‘ => [ ‘class‘ => ‘yii edisConnection‘, ‘password‘=>‘123456‘, ‘database‘=>‘database0‘, ], // 队列 ‘queue‘ => [ ‘class‘ => yiiqueue edisQueue::class, ‘redis‘ => ‘redis‘, ‘channel‘ => ‘defaultqueue‘ ], ], require (__DIR__ . ‘/components.php‘) ), ‘modules‘=>array_merge( require (__DIR__ . ‘/../../common/config/modules.php‘), require (__DIR__ . ‘/modules.php‘) ), ‘bootstrap‘ => [‘log‘], ‘vendorPath‘ => dirname(dirname(__DIR__)) . ‘/vendor‘, ‘language‘=>‘zh-CN‘, // 用户配置的语言 ‘timeZone‘=>‘PRC‘, ); /* { 构造函数 { 预初始化配置 { 设置 basePath 路径 设置 vendorPath 路径 设置 runtimePath 路径 设置 timeZone 时区 配置 container 核心组件添加到 $config 中 } 注册错误处理器 { 异常处理器 错误处理器 崩溃处理器 } 配置 & 初始化 { 设置 $config 中的属性到 yiiwebApplication 初始化 { 注册别名 { Yii::setAlias(‘@webroot‘, dirname($request->getScriptFile())); Yii::setAlias(‘@web‘, $request->getBaseUrl()); } 调用组件的 bootstrap 方法 } } } 执行 { 触发 self::EVENT_BEFORE_REQUEST 事件 解析路由 创建 Controller 对象 { 查找 yiiwebApplication->controllerMap 的配置 递归查找 模块 的配置 创建 Controller 对象 } 执行 Action { 创建 Action 对象 { 查找 Controller 中的 actions 方法 是否存在 action 对象的映射,直接返回Action对象 反射查找action方法,创建yiiaseInlineAction对象 } 执行 Action 对象 { 从父模块到子模块的,依次调用模块的 beforeAction 方法 触发 self::EVENT_BEFORE_ACTION 事件 识别 action 绑定的参数,调用 action 方法 触发 self::EVENT_AFTER_ACTION 事件 从子模块到父模块的,依次调用模块的 afterAction 方法 } } 触发 self::EVENT_AFTER_REQUEST 事件 } } */ (new yiiwebApplication($config)) { yiiaseApplication::__construct() { Yii::$app = $this; static::setInstance($this); { if ($instance === null) { unset(Yii::$app->loadedModules[get_called_class()]); } else { Yii::$app->loadedModules[get_class($instance)] = $instance; } } $this->state = self::STATE_BEGIN; $this->preInit($config); { if (!isset($config[‘id‘])) { throw new InvalidConfigException(‘The "id" configuration for the Application is required.‘); } if (isset($config[‘basePath‘])) { // basePath 路径 $this->setBasePath($config[‘basePath‘]); { parent::setBasePath($path); Yii::setAlias(‘@app‘, $this->getBasePath()); // 设置别名 } unset($config[‘basePath‘]); } else { throw new InvalidConfigException(‘The "basePath" configuration for the Application is required.‘); } if (isset($config[‘vendorPath‘])) { // vendorPath 路径 $this->setVendorPath($config[‘vendorPath‘]); { // @@vendor、@vendor、 $this->_vendorPath = Yii::getAlias($path); Yii::setAlias(‘@vendor‘, $this->_vendorPath); // 设置别名 Yii::setAlias(‘@bower‘, $this->_vendorPath . DIRECTORY_SEPARATOR . ‘bower‘); Yii::setAlias(‘@npm‘, $this->_vendorPath . DIRECTORY_SEPARATOR . ‘npm‘); } unset($config[‘vendorPath‘]); } else { // set "@vendor" $this->getVendorPath(); } if (isset($config[‘runtimePath‘])) { // runtimePath 路径 $this->setRuntimePath($config[‘runtimePath‘]); { $this->_runtimePath = Yii::getAlias($path); Yii::setAlias(‘@runtime‘, $this->_runtimePath); // 设置别名 } unset($config[‘runtimePath‘]); } else { // set "@runtime" $this->getRuntimePath(); } if (isset($config[‘timeZone‘])) { // timeZone 时区 $this->setTimeZone($config[‘timeZone‘]); { date_default_timezone_set($value); } unset($config[‘timeZone‘]); } elseif (!ini_get(‘date.timezone‘)) { $this->setTimeZone(‘UTC‘); } if (isset($config[‘container‘])) { $this->setContainer($config[‘container‘]); { Yii::configure(Yii::$container, $config); // 配置 container } unset($config[‘container‘]); } // merge core components with custom components foreach ($this->coreComponents(){ yiiwebApplication::coreComponents { return array_merge(parent::coreComponents(){ return [ ‘log‘ => [‘class‘ => ‘yiilogDispatcher‘], ‘view‘ => [‘class‘ => ‘yiiwebView‘], ‘formatter‘ => [‘class‘ => ‘yiii18nFormatter‘], ‘i18n‘ => [‘class‘ => ‘yiii18nI18N‘], ‘mailer‘ => [‘class‘ => ‘yiiswiftmailerMailer‘], ‘urlManager‘ => [‘class‘ => ‘yiiwebUrlManager‘], ‘assetManager‘ => [‘class‘ => ‘yiiwebAssetManager‘], ‘security‘ => [‘class‘ => ‘yiiaseSecurity‘], ]; }, [ ‘request‘ => [‘class‘ => ‘yiiwebRequest‘], ‘response‘ => [‘class‘ => ‘yiiwebResponse‘], ‘session‘ => [‘class‘ => ‘yiiwebSession‘], ‘user‘ => [‘class‘ => ‘yiiwebUser‘], ‘errorHandler‘ => [‘class‘ => ‘yiiwebErrorHandler‘], ]); } } as $id => $component) { // 核心组件添加到 $config 中 if (!isset($config[‘components‘][$id])) { $config[‘components‘][$id] = $component; } elseif (is_array($config[‘components‘][$id]) && !isset($config[‘components‘][$id][‘class‘])) { $config[‘components‘][$id][‘class‘] = $component[‘class‘]; } } } $this->registerErrorHandler($config); // 注册错误处理器 { if (YII_ENABLE_ERROR_HANDLER) { if (!isset($config[‘components‘][‘errorHandler‘][‘class‘])) { echo "Error: no errorHandler component is configured. "; exit(1); } $this->set(‘errorHandler‘, $config[‘components‘][‘errorHandler‘]); unset($config[‘components‘][‘errorHandler‘]); $this->getErrorHandler()->register(); { yiiaseErrorHandler::register() { ini_set(‘display_errors‘, false); set_exception_handler([$this, ‘handleException‘]); // 异常处理器 if (defined(‘HHVM_VERSION‘)) { set_error_handler([$this, ‘handleHhvmError‘]); } else { set_error_handler([$this, ‘handleError‘]); // 错误处理器 } if ($this->memoryReserveSize > 0) { $this->_memoryReserve = str_repeat(‘x‘, $this->memoryReserveSize); } register_shutdown_function([$this, ‘handleFatalError‘]); // 崩溃处理器 } } } } Component::__construct($config); { if (!empty($config)) { Yii::configure($this, $config); // 设置 $config 中的属性到 yiiwebApplication { foreach ($config as $name => $value) { $object->$name = $value; } return $object; } } $this->init(); { yiiaseApplication::init { $this->state = self::STATE_INIT; $this->bootstrap(); { yiiwebApplication::bootstrap() { $request = $this->getRequest(); Yii::setAlias(‘@webroot‘, dirname($request->getScriptFile())); Yii::setAlias(‘@web‘, $request->getBaseUrl()); parent::bootstrap(); { yiiaseApplication::bootstrap() { if ($this->extensions === null) { $file = Yii::getAlias(‘@vendor/yiisoft/extensions.php‘); $this->extensions = is_file($file) ? include($file) : []; } foreach ($this->extensions as $extension) { if (!empty($extension[‘alias‘])) { foreach ($extension[‘alias‘] as $name => $path) { Yii::setAlias($name, $path); } } if (isset($extension[‘bootstrap‘])) { $component = Yii::createObject($extension[‘bootstrap‘]); if ($component instanceof BootstrapInterface) { Yii::trace(‘Bootstrap with ‘ . get_class($component) . ‘::bootstrap()‘, __METHOD__); $component->bootstrap($this); } else { Yii::trace(‘Bootstrap with ‘ . get_class($component), __METHOD__); } } } foreach ($this->bootstrap as $class) { // 要立即启动的组件,$this->bootstrap = [‘log‘] $component = null; if (is_string($class)) { if ($this->has($class)) { $component = $this->get($class); // 获取组件 } elseif ($this->hasModule($class)) { $component = $this->getModule($class); } elseif (strpos($class, ‘\‘) === false) { throw new InvalidConfigException("Unknown bootstrapping component ID: $class"); } } if (!isset($component)) { $component = Yii::createObject($class); } if ($component instanceof BootstrapInterface) { Yii::trace(‘Bootstrap with ‘ . get_class($component) . ‘::bootstrap()‘, __METHOD__); $component->bootstrap($this); // 调用组件的 bootstrap 方法 } else { Yii::trace(‘Bootstrap with ‘ . get_class($component), __METHOD__); } } } } } } } } } } }->run();{ yiiaseApplication::run() { try { $this->state = self::STATE_BEFORE_REQUEST; $this->trigger(self::EVENT_BEFORE_REQUEST); // 触发事件 { $this->ensureBehaviors(); { if ($this->_behaviors === null) { 当 $this->_behaviors 为 null $this->_behaviors = []; // 设置 $this->_behaviors 为空数组 foreach ($this->behaviors(){ return []; } as $name => $behavior) { $this->attachBehaviorInternal($name, $behavior); { if (!($behavior instanceof Behavior)) { $behavior = Yii::createObject($behavior); // 创建 $behavior 对象 } if (is_int($name)) { // 没有指定 $behavior 的 name $behavior->attach($this); // 调用 $behavior 的 attach 方法 $this->_behaviors[] = $behavior; } else { if (isset($this->_behaviors[$name])) { $this->_behaviors[$name]->detach(); // 调用 $behavior 的 detach 方法 } $behavior->attach($this); // 调用 $behavior 的 attach 方法 { 如:$behavior = yiifiltersRateLimiter yiiaseActionFilter::attach($owner) { $this->owner = $owner; // $owner === yiiwebApplication $owner->on(Controller::EVENT_BEFORE_ACTION, [$this, ‘beforeFilter‘]); // 注册事件 { yiiaseComponent::on($name, $handler, $data = null, $append = true) { $this->ensureBehaviors(); if ($append || empty($this->_events[$name])) { $this->_events[$name][] = [$handler, $data]; // 增加事件处理器 } else { array_unshift($this->_events[$name], [$handler, $data]); } } } } } $this->_behaviors[$name] = $behavior; } return $behavior; } } } } if (!empty($this->_events[$name])) { if ($event === null) { $event = new Event; // 创建 $event 对象 } if ($event->sender === null) { $event->sender = $this; } $event->handled = false; $event->name = $name; foreach ($this->_events[$name] as $handler) { // 事件处理器列表 $event->data = $handler[1]; // 事件处理器的参数 call_user_func($handler[0], $event); // 调用事件处理器 // stop further handling if the event is handled if ($event->handled) { return; } } } // invoke class-level attached handlers Event::trigger($this, $name, $event); // 调用类级别的事件处理器 { yiiaseEvent::trigger($class, $name, $event = null) { if (empty(self::$_events[$name])) { return; } if ($event === null) { $event = new static; } $event->handled = false; $event->name = $name; if (is_object($class)) { // 如 $class === yiiwebApplication if ($event->sender === null) { $event->sender = $class; } $class = get_class($class); } else { $class = ltrim($class, ‘\‘); } $classes = array_merge( [$class], class_parents($class, true), class_implements($class, true) ); /* self::$_events = [ yiiwebApplication::EVENT_BEFORE_REQUEST=>[ yiiwebApplication::class=>[ [$handlerFunc0,$data0] [$handlerFunc1,$data1] ] ] ] */ foreach ($classes as $class) { if (empty(self::$_events[$name][$class])) { continue; } foreach (self::$_events[$name][$class] as $handler) { // 事件处理器 $event->data = $handler[1]; call_user_func($handler[0], $event); if ($event->handled) { return; } } } } } } $this->state = self::STATE_HANDLING_REQUEST; $response = $this->handleRequest($this->getRequest()); // 处理请求 { yiiwebApplication::handleRequest($request) { if (empty($this->catchAll)) { // 没有配置全局捕获 try { list ($route, $params) = $request->resolve(); // 解析路由 { $result = Yii::$app->getUrlManager()->parseRequest($this); { yiiwebUrlManager::parseRequest($request) { if ($this->enablePrettyUrl) { // 使用伪静态 /* @var $rule UrlRule */ foreach ($this->rules as $rule) { $result = $rule->parseRequest($this, $request); if (YII_DEBUG) { Yii::trace([ ‘rule‘ => method_exists($rule, ‘__toString‘) ? $rule->__toString() : get_class($rule), ‘match‘ => $result !== false, ‘parent‘ => null, ], __METHOD__); } if ($result !== false) { return $result; } } if ($this->enableStrictParsing) { return false; } Yii::trace(‘No matching URL rules. Using default URL parsing logic.‘, __METHOD__); $suffix = (string) $this->suffix; $pathInfo = $request->getPathInfo(); $normalized = false; if ($this->normalizer !== false) { $pathInfo = $this->normalizer->normalizePathInfo($pathInfo, $suffix, $normalized); } if ($suffix !== ‘‘ && $pathInfo !== ‘‘) { $n = strlen($this->suffix); if (substr_compare($pathInfo, $this->suffix, -$n, $n) === 0) { $pathInfo = substr($pathInfo, 0, -$n); if ($pathInfo === ‘‘) { // suffix alone is not allowed return false; } } else { // suffix doesn‘t match return false; } } if ($normalized) { // pathInfo was changed by normalizer - we need also normalize route return $this->normalizer->normalizeRoute([$pathInfo, []]); } else { return [$pathInfo, []]; } } else { Yii::trace(‘Pretty URL not enabled. Using default URL parsing logic.‘, __METHOD__); $route = $request->getQueryParam($this->routeParam, ‘‘); // $routeParam = ‘r‘; // 不使用伪静态 if (is_array($route)) { $route = ‘‘; } return [(string) $route, []]; } } } // 路由识别结束,获取Query参数 if ($result !== false) { list ($route, $params) = $result; if ($this->_queryParams === null) { $_GET = $params + $_GET; // preserve numeric keys } else { $this->_queryParams = $params + $this->_queryParams; } return [$route, $this->getQueryParams()]; } throw new NotFoundHttpException(Yii::t(‘yii‘, ‘Page not found.‘)); } } catch (UrlNormalizerRedirectException $e) { $url = $e->url; if (is_array($url)) { if (isset($url[0])) { // ensure the route is absolute $url[0] = ‘/‘ . ltrim($url[0], ‘/‘); } $url += $request->getQueryParams(); } return $this->getResponse()->redirect(Url::to($url, $e->scheme), $e->statusCode); } } else { $route = $this->catchAll[0]; $params = $this->catchAll; unset($params[0]); } try { Yii::trace("Route requested: ‘$route‘", __METHOD__); $this->requestedRoute = $route; // 识别到的路由,如: $route = "/database-module/keyvalue-sample/redis-demo/foo-method" $result = $this->runAction($route, $params); // 执行action { yiiaseModule::runAction($route, $params = []) { $parts = $this->createController($route); // 创建 Controller 对象 { if ($route === ‘‘) { $route = $this->defaultRoute; // ‘default‘ } // double slashes or leading/ending slashes may cause substr problem $route = trim($route, ‘/‘); if (strpos($route, ‘//‘) !== false) { return false; } if (strpos($route, ‘/‘) !== false) { list ($id, $route) = explode(‘/‘, $route, 2); } else { $id = $route; $route = ‘‘; } // module and controller map take precedence if (isset($this->controllerMap[$id])) { // 查找 yiiwebApplication->controllerMap 的配置 $controller = Yii::createObject($this->controllerMap[$id], [$id, $this]); return [$controller, $route]; } $module = $this->getModule($id); // 查找 模块 的配置 { yiiaseModule::getModule($id, $load = true) { if (($pos = strpos($id, ‘/‘)) !== false) { // sub-module $module = $this->getModule(substr($id, 0, $pos)); // 递归查找"子模块" return $module === null ? null : $module->getModule(substr($id, $pos + 1), $load); } if (isset($this->_modules[$id])) { if ($this->_modules[$id] instanceof Module) { return $this->_modules[$id]; } elseif ($load) { Yii::trace("Loading module: $id", __METHOD__); /* @var $module Module */ $module = Yii::createObject($this->_modules[$id], [$id, $this]); // 创建模块 { yiiaseModule::__construct($id, $parent = null, $config = []) { $this->id = $id; // 模块 Id,如:$id = ‘database-module‘ $this->module = $parent; // 父级别模块,如:$parent = yiiwebApplication parent::__construct($config); } } $module->setInstance($module); // 对自身的依赖 return $this->_modules[$id] = $module; // 设置模块到父级别的_modules中 } } return null; } } if ($module !== null) { return $module->createController($route); // 递归调用 创建 Controller 对象 } if (($pos = strrpos($route, ‘/‘)) !== false) { // 最右边的"/" $id .= ‘/‘ . substr($route, 0, $pos); $route = substr($route, $pos + 1); } $controller = $this->createControllerByID($id); { // 如: $id = ‘redis-demo‘ $pos = strrpos($id, ‘/‘); // 控制器id中的"/" if ($pos === false) { $prefix = ‘‘; $className = $id; } else { // 控制器id中带有"/" $prefix = substr($id, 0, $pos + 1); // 签字 $className = substr($id, $pos + 1); } // 如: $className = ‘redis-demo‘ if (!preg_match(‘%^[a-z][a-z0-9\-_]*$%‘, $className)) { // 只支持小写字母、数字、横杠、下划线 return null; } if ($prefix !== ‘‘ && !preg_match(‘%^[a-z0-9_/]+$%i‘, $prefix)) { // 只支持小写字母、数字 return null; } $className = str_replace(‘ ‘, ‘‘, ucwords(str_replace(‘-‘, ‘ ‘, $className))) . ‘Controller‘; // 横杠转成驼峰 // 如: $className = ‘RedisDemoController‘ $className = ltrim($this->controllerNamespace . ‘\‘ . str_replace(‘/‘, ‘\‘, $prefix) . $className, ‘\‘); // 拼接 Controller 的类名 if (strpos($className, ‘-‘) !== false || !class_exists($className)) { return null; } if (is_subclass_of($className, ‘yiiaseController‘)) { // 是 yiiaseController 的子类 // 如: $id = ‘redis-demo‘ $controller = Yii::createObject($className, [$id, $this]); // 创建 Controller 对象 { yiiaseController::__construct($id, $module, $config = []) { $this->id = $id; // 如: $id = ‘redis-demo‘ $this->module = $module; // 如:$module = yiiwebApplication 或者 debugmodulemodulesmodule0Module parent::__construct($config); } } return get_class($controller) === $className ? $controller : null; } elseif (YII_DEBUG) { throw new InvalidConfigException("Controller class must extend from \yii\base\Controller."); } return null; } if ($controller === null && $route !== ‘‘) { $controller = $this->createControllerByID($id . ‘/‘ . $route); // controller下存在子目录 $route = ‘‘; } return $controller === null ? false : [$controller, $route]; } if (is_array($parts)) { /* @var $controller Controller */ // 如:$controller === ‘RedisDemoController‘ 对象 // 如:$actionID === ‘foo-method‘ list($controller, $actionID) = $parts; $oldController = Yii::$app->controller; Yii::$app->controller = $controller; $result = $controller->runAction($actionID, $params); { yiiaseController::runAction($id, $params = []) { $action = $this->createAction($id); { // 如:$id === ‘foo-method‘ yiiaseController::createAction($id) { if ($id === ‘‘) { $id = $this->defaultAction; // $defaultAction = ‘index‘; } $actionMap = $this->actions(); // Controller 中的 actions 方法 { return []; } if (isset($actionMap[$id])) { // 存在 action 对象的映射 return Yii::createObject($actionMap[$id], [$id, $this]); // 创建 action 对象 } elseif (preg_match(‘/^[a-z0-9\-_]+$/‘, $id) && strpos($id, ‘--‘) === false && trim($id, ‘-‘) === $id) { $methodName = ‘action‘ . str_replace(‘ ‘, ‘‘, ucwords(implode(‘ ‘, explode(‘-‘, $id)))); // 下划线转成驼峰 // 如:$methodName = ‘actionFooMethod‘ if (method_exists($this, $methodName)) { $method = new ReflectionMethod($this, $methodName); if ($method->isPublic() && $method->getName() === $methodName) { // 公有的 return new InlineAction($id, $this, $methodName); { yiiaseInlineAction::__construct($id, $controller, $actionMethod, $config = []) { $this->actionMethod = $actionMethod; // $actionMethod = ‘actionFooMethod‘ parent::__construct($id, $controller, $config); { yiiaseAction::__construct($id, $controller, $config = []) { $this->id = $id; // 如:$id === ‘foo-method‘ $this->controller = $controller; // 如:$controller === Controller 对象 parent::__construct($config); } } } } } } } return null; } } if ($action === null) { throw new InvalidRouteException(‘Unable to resolve the request: ‘ . $this->getUniqueId() . ‘/‘ . $id); } Yii::trace(‘Route to run: ‘ . $action->getUniqueId(), __METHOD__); if (Yii::$app->requestedAction === null) { Yii::$app->requestedAction = $action; } $oldAction = $this->action; $this->action = $action; $modules = []; $runAction = true; // call beforeAction on modules foreach ($this->getModules(){ // 递归获取父级别的模块$module $modules = [$this->module]; $module = $this->module; // 模块 while ($module->module !== null) { // 有父模块 array_unshift($modules, $module->module); // 父模块放到栈顶 $module = $module->module; } return $modules; } as $module) { if ($module->beforeAction($action)) { // 从父模块到子模块的,依次调用模块的 beforeAction 方法 array_unshift($modules, $module); // 父模块放到栈底 } else { $runAction = false; break; } } $result = null; if ($runAction && $this->beforeAction($action){ yiiaseController::beforeAction($action) { $event = new ActionEvent($action); $this->trigger(self::EVENT_BEFORE_ACTION, $event); // 触发事件 { $this->ensureBehaviors(); { if ($this->_behaviors === null) { 当 $this->_behaviors 为 null $this->_behaviors = []; // 设置 $this->_behaviors 为空数组 foreach ($this->behaviors(){ return []; } as $name => $behavior) { $this->attachBehaviorInternal($name, $behavior); { if (!($behavior instanceof Behavior)) { $behavior = Yii::createObject($behavior); // 创建 $behavior 对象 } if (is_int($name)) { // 没有指定 $behavior 的 name $behavior->attach($this); // 调用 $behavior 的 attach 方法 $this->_behaviors[] = $behavior; } else { if (isset($this->_behaviors[$name])) { $this->_behaviors[$name]->detach(); // 调用 $behavior 的 detach 方法 } $behavior->attach($this); // 调用 $behavior 的 attach 方法 { 如:$behavior = yiifiltersRateLimiter yiiaseActionFilter::attach($owner) { $this->owner = $owner; // $owner === yiiwebApplication $owner->on(Controller::EVENT_BEFORE_ACTION, [$this, ‘beforeFilter‘]); // 注册事件 { yiiaseComponent::on($name, $handler, $data = null, $append = true) { $this->ensureBehaviors(); if ($append || empty($this->_events[$name])) { $this->_events[$name][] = [$handler, $data]; // 增加事件处理器 } else { array_unshift($this->_events[$name], [$handler, $data]); } } } } } $this->_behaviors[$name] = $behavior; } return $behavior; } } } } if (!empty($this->_events[$name])) { if ($event === null) { $event = new Event; // 创建 $event 对象 } if ($event->sender === null) { $event->sender = $this; } $event->handled = false; $event->name = $name; foreach ($this->_events[$name] as $handler) { // 事件处理器列表 $event->data = $handler[1]; // 事件处理器的参数 call_user_func($handler[0], $event); // 调用事件处理器 // stop further handling if the event is handled if ($event->handled) { return; } } } // invoke class-level attached handlers Event::trigger($this, $name, $event); // 调用类级别的事件处理器 { yiiaseEvent::trigger($class, $name, $event = null) { if (empty(self::$_events[$name])) { return; } if ($event === null) { $event = new static; } $event->handled = false; $event->name = $name; if (is_object($class)) { // 如 $class === yiiwebApplication if ($event->sender === null) { $event->sender = $class; } $class = get_class($class); } else { $class = ltrim($class, ‘\‘); } $classes = array_merge( [$class], class_parents($class, true), class_implements($class, true) ); /* self::$_events = [ yiiaseController::EVENT_BEFORE_ACTION=>[ yiiaseController::class=>[ [$handlerFunc0,$data0] [$handlerFunc1,$data1] ] ] ] */ foreach ($classes as $class) { if (empty(self::$_events[$name][$class])) { continue; } foreach (self::$_events[$name][$class] as $handler) { // 事件处理器 $event->data = $handler[1]; call_user_func($handler[0], $event); if ($event->handled) { return; } } } } } } return $event->isValid; } }) { // 触发事件,并且返回 true // run the action $result = $action->runWithParams($params); { yiiaseInlineAction::runWithParams($params) { $args = $this->controller->bindActionParams($this, $params); { yiiwebController::bindActionParams($action, $params) { if ($action instanceof InlineAction) { // 反射 action 参数 $method = new ReflectionMethod($this, $action->actionMethod); } else { $method = new ReflectionMethod($action, ‘run‘); } $args = []; $missing = []; $actionParams = []; foreach ($method->getParameters() as $param) { // action 方法的参数 $name = $param->getName(); // 参数名 if (array_key_exists($name, $params)) { if ($param->isArray()) { $args[] = $actionParams[$name] = (array) $params[$name]; } elseif (!is_array($params[$name])) { $args[] = $actionParams[$name] = $params[$name]; } else { throw new BadRequestHttpException(Yii::t(‘yii‘, ‘Invalid data received for parameter "{param}".‘, [ ‘param‘ => $name, ])); } unset($params[$name]); } elseif ($param->isDefaultValueAvailable()) { // 参数有默认值 $args[] = $actionParams[$name] = $param->getDefaultValue(); } else { $missing[] = $name; } } if (!empty($missing)) { throw new BadRequestHttpException(Yii::t(‘yii‘, ‘Missing required parameters: {params}‘, [ ‘params‘ => implode(‘, ‘, $missing), ])); } $this->actionParams = $actionParams; return $args; } } Yii::trace(‘Running action: ‘ . get_class($this->controller) . ‘::‘ . $this->actionMethod . ‘()‘, __METHOD__); if (Yii::$app->requestedParams === null) { Yii::$app->requestedParams = $args; } return call_user_func_array([$this->controller, $this->actionMethod], $args); // 调用 action 方法 } } $result = $this->afterAction($action, $result); { yiiaseController::afterAction($action, $result) { $event = new ActionEvent($action); $event->result = $result; $this->trigger(self::EVENT_AFTER_ACTION, $event); // 触发事件 return $event->result; } } // call afterAction on modules foreach ($modules as $module) { // 从子模块到父模块的,依次调用模块的 afterAction 方法 /* @var $module Module */ $result = $module->afterAction($action, $result); } } if ($oldAction !== null) { $this->action = $oldAction; } return $result; } } if ($oldController !== null) { Yii::$app->controller = $oldController; } return $result; } $id = $this->getUniqueId(); throw new InvalidRouteException(‘Unable to resolve the request "‘ . ($id === ‘‘ ? $route : $id . ‘/‘ . $route) . ‘".‘); } } if ($result instanceof Response) { // 响应结果,action 返回的结果是对象 return $result; } else { $response = $this->getResponse(); if ($result !== null) { $response->data = $result; // 响应结果,action 返回的结果是字符串 } return $response; } } catch (InvalidRouteException $e) { throw new NotFoundHttpException(Yii::t(‘yii‘, ‘Page not found.‘), $e->getCode(), $e); } } } $this->state = self::STATE_AFTER_REQUEST; $this->trigger(self::EVENT_AFTER_REQUEST); $this->state = self::STATE_SENDING_RESPONSE; $response->send(); // 发送响应数据 $this->state = self::STATE_END; return $response->exitStatus; } catch (ExitException $e) { // 出现异常 $this->end($e->statusCode, isset($response) ? $response : null); { if ($this->state === self::STATE_BEFORE_REQUEST || $this->state === self::STATE_HANDLING_REQUEST) { $this->state = self::STATE_AFTER_REQUEST; $this->trigger(self::EVENT_AFTER_REQUEST); } if ($this->state !== self::STATE_SENDING_RESPONSE && $this->state !== self::STATE_END) { $this->state = self::STATE_END; $response = $response ? : $this->getResponse(); $response->send(); // 发送响应数据 } if (YII_ENV_TEST) { throw new ExitException($status); } else { exit($status); } } return $e->statusCode; } } }
以上是关于Yii 2.0.6 - 从入口到Action执行的主要内容,如果未能解决你的问题,请参考以下文章