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'); // 注册类加载器

require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');

Yii::setAlias('@common', dirname(__DIR__)); // 注册别名

$config = array(
    'id'=>'app-debugmodule',
    'basePath'=>dirname(__DIR__),
    'controllerNamespace'=>'debugmodule\controllers',
    'defaultRoute'=>'index/index',
    'params'=>[
        'adminEmail' => 'admin@example.com',
        'supportEmail' => 'support@example.com',
        'user.passwordResetTokenExpire' => 3600,
    ],
    'components'=>array_merge(
        [
            'cache' => [
                'class' => 'yii\caching\FileCache',
                'cachePath' => '@runtime/cache',
            ],
            'log' => [
                'class' => 'yii\log\Dispatcher',
                   'traceLevel' => YII_DEBUG ? 3 : 0,
                   'targets' => [
                       [
                           'class' => 'yii\log\FileTarget',
                           'levels' => ['error', 'warning'],
                           'enabled' => true,
                           'logFile'=>'@runtime/logs/app.log',
                           'categories' => [], // 全部记录
                           'except' => ['yii\db\*'], // 不记录的分类
                           'logVars' => [],
                           // 'logVars' => ['_GET', '_POST', '_FILES', '_COOKIE', '_SESSION', '_SERVER'],
                       ],
                   ],
            ],
            'mailer' => [
                'class' => 'yii\swiftmailer\Mailer',
                'transport' => array( // 发送到互联网的传输方法
                    'class'=>'Swift_Transport_MailTransport',
                    'constructArgs'=>array(
                        array('class'=>'Swift_Transport_SimpleMailInvoker'),
                        array('class'=>'Swift_Events_SimpleEventDispatcher')
                    )
                )
            ],
            'security' => [
                'class' => 'yii\base\Security'
            ],
            'i18n' => [
                'class' => 'yii\i18n\I18N',
                'translations'=>[
                    'common'=>[ // 语言转换器
                        'class' => 'yii\i18n\PhpMessageSource',
                        'basePath' => '@common/messages',
                    ],
                    'debugmodule'=>[
                        'class' => 'yii\i18n\PhpMessageSource',
                        'basePath' => '@debugmodule/messages',
                    ],
                    '*'=>[ // 默认语言转换器
                        'class' => 'yii\i18n\PhpMessageSource',
                        'basePath' => '@common/messages',
                    ]
                ]
            ],
            // radis
            'redis' => [
                'class' => 'yii\redis\Connection',
                'password'=>'123456',
                'database'=>'database0',
            ],
            // 队列
            'queue' => [
               'class' => \yii\queue\redis\Queue::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 中的属性到 \yii\web\Application

            初始化
            {
                注册别名
                {
                    Yii::setAlias('@webroot', dirname($request->getScriptFile()));
                    Yii::setAlias('@web', $request->getBaseUrl());
                }
                调用组件的 bootstrap 方法
            }

        }
    }

    执行
    {
        触发 self::EVENT_BEFORE_REQUEST 事件
        解析路由
        创建 Controller 对象
        {
            查找 \yii\web\Application->controllerMap 的配置
            递归查找 模块 的配置
            创建 Controller 对象
        }

        执行 Action
        {
            创建 Action 对象
            {
                查找 Controller 中的 actions 方法 是否存在 action 对象的映射,直接返回Action对象
                反射查找action方法,创建\yii\base\InlineAction对象
            }

            执行 Action 对象
            {
                从父模块到子模块的,依次调用模块的 beforeAction 方法
                触发 self::EVENT_BEFORE_ACTION 事件
                识别 action 绑定的参数,调用 action 方法
                触发 self::EVENT_AFTER_ACTION 事件
                从子模块到父模块的,依次调用模块的 afterAction 方法
            }
        }

        触发 self::EVENT_AFTER_REQUEST 事件
    }
}

*/
(new yii\web\Application($config))
{
    \yii\base\Application::__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(){
                \yii\web\Application::coreComponents
                {
                    return array_merge(parent::coreComponents(){
                        return [
                            'log' => ['class' => 'yii\log\Dispatcher'],
                            'view' => ['class' => 'yii\web\View'],
                            'formatter' => ['class' => 'yii\i18n\Formatter'],
                            'i18n' => ['class' => 'yii\i18n\I18N'],
                            'mailer' => ['class' => 'yii\swiftmailer\Mailer'],
                            'urlManager' => ['class' => 'yii\web\UrlManager'],
                            'assetManager' => ['class' => 'yii\web\AssetManager'],
                            'security' => ['class' => 'yii\base\Security'],
                        ];
                    }, [
                        'request' => ['class' => 'yii\web\Request'],
                        'response' => ['class' => 'yii\web\Response'],
                        'session' => ['class' => 'yii\web\Session'],
                        'user' => ['class' => 'yii\web\User'],
                        'errorHandler' => ['class' => 'yii\web\ErrorHandler'],
                    ]);
                }

            } 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.\n";
                    exit(1);
                }
                $this->set('errorHandler', $config['components']['errorHandler']);
                unset($config['components']['errorHandler']);
                $this->getErrorHandler()->register();
                {
                    \yii\base\ErrorHandler::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 中的属性到 \yii\web\Application
                {
                    foreach ($config as $name => $value) {
                        $object->$name = $value;
                    }
                    return $object;
                }
            }

            $this->init();
            {
                \yii\base\Application::init
                {
                    $this->state = self::STATE_INIT;
                    $this->bootstrap();
                    {
                        \yii\web\Application::bootstrap()
                        {
                            $request = $this->getRequest();
                            Yii::setAlias('@webroot', dirname($request->getScriptFile()));
                            Yii::setAlias('@web', $request->getBaseUrl());

                            parent::bootstrap();
                            {
                                \yii\base\Application::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();{
    \yii\base\Application::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 = \yii\filters\RateLimiter
                                        \yii\base\ActionFilter::attach($owner)
                                        {
                                            $this->owner = $owner; // $owner === \yii\web\Application
                                            $owner->on(Controller::EVENT_BEFORE_ACTION, [$this, 'beforeFilter']); // 注册事件
                                            {
                                                \yii\base\Component::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); // 调用类级别的事件处理器
                {
                    \yii\base\Event::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 === \yii\web\Application
                            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 = [
                                \yii\web\Application::EVENT_BEFORE_REQUEST=>[
                                    \yii\web\Application::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()); // 处理请求
            {
                \yii\web\Application::handleRequest($request)
                {
                    if (empty($this->catchAll)) { // 没有配置全局捕获
                        try {
                            list ($route, $params) = $request->resolve(); // 解析路由
                            {
                                $result = Yii::$app->getUrlManager()->parseRequest($this);
                                {
                                    \yii\web\UrlManager::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
                        {
                            \yii\base\Module::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])) { // 查找 \yii\web\Application->controllerMap 的配置
                                        $controller = Yii::createObject($this->controllerMap[$id], [$id, $this]);
                                        return [$controller, $route];
                                    }
                                    $module = $this->getModule($id); // 查找 模块 的配置
                                    {
                                        \yii\base\Module::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]); // 创建模块
                                                    {
                                                        \yii\base\Module::__construct($id, $parent = null, $config = [])
                                                        {
                                                            $this->id = $id; // 模块 Id,如:$id = 'database-module'
                                                            $this->module = $parent; // 父级别模块,如:$parent = \yii\web\Application
                                                            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, 'yii\base\Controller')) { // 是 yii\base\Controller 的子类
                                            // 如: $id = 'redis-demo'
                                            $controller = Yii::createObject($className, [$id, $this]); // 创建 Controller 对象
                                            {
                                                \yii\base\Controller::__construct($id, $module, $config = [])
                                                {
                                                    $this->id = $id; // 如: $id = 'redis-demo'
                                                    $this->module = $module; //  如:$module = \yii\web\Application 或者 \debugmodule\modules\module0\Module
                                                    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);
                                    {
                                        \yii\base\Controller::runAction($id, $params = [])
                                        {
                                            $action = $this->createAction($id);
                                            {
                                                // 如:$id === 'foo-method'
                                                \yii\base\Controller::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);
                                                                {
                                                                    \yii\base\InlineAction::__construct($id, $controller, $actionMethod, $config = [])
                                                                    {
                                                                        $this->actionMethod = $actionMethod; // $actionMethod = 'actionFooMethod'
                                                                        parent::__construct($id, $controller, $config);
                                                                        {
                                                                            \yii\base\Action::__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){
                                                \yii\base\Controller::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 = \yii\filters\RateLimiter
                                                                                \yii\base\ActionFilter::attach($owner)
                                                                                {
                                                                                    $this->owner = $owner; // $owner === \yii\web\Application
                                                                                    $owner->on(Controller::EVENT_BEFORE_ACTION, [$this, 'beforeFilter']); // 注册事件
                                                                                    {
                                                                                        \yii\base\Component::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); // 调用类级别的事件处理器
                                                        {
                                                            \yii\base\Event::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 === \yii\web\Application
                                                                    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 = [
                                                                        \yii\base\Controller::EVENT_BEFORE_ACTION=>[
                                                                            \yii\base\Controller::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);
                                                {
                                                    \yii\base\InlineAction::runWithParams($params)
                                                    {
                                                        $args = $this->controller->bindActionParams($this, $params);
                                                        {
                                                            \yii\web\Controller::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);
                                                {
                                                     \yii\base\Controller::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;

        }
    }
}

  

原文地址:https://www.cnblogs.com/xiaoyaogege/p/10368980.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


1、将Yii2.0advanced版中应用主体frontend或backend应用复制为api应用2、在应用主体api目录的controller新建SiteController.php:namespaceapi\controllers;useYii;useyii\rest\ActiveController;/*SiteController测试控制器*/classSiteControllerextendsActiveCon
Yii2restfulAPI文档一、配置模块:1.Config/main.php:  2.创建模块目录:  3.Module.php:  二、路由配置:  三、控制器:  四、Models:   五、测试:GET:  POST:  PUT:      DELETE:  
Yii在framework/i18n/data/%lang%.php文件中有很多翻译.这是例如germantranslations我想在我的Yii项目中使用Fullcalendar.要翻译此日历,我必须为当前语言提供一个monthNames/dayNames数组.FullcalendarmonthNamesDocumentationYii生成数组的最佳方法是什么:['January'
在Yii2中,官方的页面多语言解决方案有两个:方案1,使用Yii::t()函数,在页面中需要输出文字的地方,使用类似如下代码:<?=Yii::t(‘views/login’,‘hello’)?>这样做的后果是页面上大量充斥着类似的代码,导致页面可读性很差,而且对于同一个页面来说,Yii::t()函数的第一个参数基本上都是
Yii2.0对数据库查询的一些简单的操作123456789101112131415161718192021222324252627282930313233343536373839User::findOne($id);   //此方法返回 主键 id=1  的一条数据(举个例子);  User::find()->where(['name' =
数据查询User::find()->all();此方法返回所有数据;User::findOne($id);此方法返回主键id=1的一条数据(举个例子);User::find()->where(['name'=>'小伙儿'])->one();此方法返回['name'=>'小伙儿']的一条数据;User::find()->where(['n
最近打算提升自己的解决问题能力,于是打算从学习其他框架下手,让我们先去了解yii框架是如何运作的吧!https://www.yiichina.com/访问yii中文网站  让我们先把框架下载下来点击下载框架 科普一下:目前yii框架有三个版本yii1.0、yii1.1、yii2.0貌似即将推出3.0 这里我们
如何在Yii2中检查模型属性的类型(列类型)?ThisoldYiiForumanswer给了我一个结论,在Yii1中我可以使用类似的东西:$model->getMetaData()->columns['attribute-name']->type;但我没有成功将此解决方案移植到Yii2.有人可以帮忙吗?解决方法:您可以使用:$model->getTableSchema()
defined('YII_DEBUG')ordefine('YII_DEBUG',true);defined('YII_ENV')ordefine('YII_ENV','dev');require(__DIR__.'/../vendor/autoload.php');//注册类加载器require(__DIR__.'/../vendor/yii
在NGINX中配置:location/{   if(!-e$request_filename){    rewrite^/(.*)/index.phplast;}这样,当NGINX找不到文件的时候,就会将URL重写为index.php。对于URL中只有域名的情况,因为不存在对应的文件,所以会匹配到。再配置:location~\.php${  include
Yii2.0封装的类足够强大,Mailer的使用方法做一个总结:1、先在main-local.php中做好配置:return[//....'components'=>['mailer'=>['class'=>'yii\swiftmailer\Mailer',],],];详细如下:return[//....'components'=>[
每当我尝试登录我的Yii应用程序时,它都会显示错误CDbConnectionfailedtoopentheDBconnection:couldnotfinddriver.我google了很多个小时,从许多博客我知道我需要pdo_mysql,但已经安装了.在php.ini中我也对这些行做了评论;extension=php_pdo_mysql.dll;extension
我有一个模型Aziende,它与称为Annunci的花药模型相关(1:N),如下所示:'annunci'=>array(self::HAS_MANY,'Annunci','azienda_id'),我想算一下有多少记录确实有这种关系,在mySql中我会做:SELECTcount(*)FROM`aziende`aJOINannuncianONan.azienda_id=a.id我怎么能
我们有一个项目,为孟加拉国最大的服装行业之一建立一个ERP系统.他们有大约20,000名员工,其中约10%的员工每个月都会离职.我们是一家拥有5名PHP开发人员的小公司,对这么大的项目没有多少经验.我们之前使用Codeigniter/ZendFramework和MySQL数据库开发了不同的中小规模项目.对于
我在Yii中有一些表单,使用以下内容以下拉形式从相关表中获取数据列表:dropDownList(CHtml::listData(Company::model()->findAll(array('order'=>'companyASC'))));这是有效的,但这意味着对于每个下拉列表(其中很多)我将这个数组(‘order’=>’公司ASC’放在每一个中.这是最
本文采用Yii文档,经过自己的修改,让读者更容易理解预定义完整列表: boolean : CBooleanValidator 的别名,确保属性的值是CBooleanValidator::trueValue 或CBooleanValidator::falseValue .captcha : CCaptchaValidator 的别名,确保了特性的值等于 CAPTCHA 显示出来
前面已经安装好了yii框架,现在我们来建立第一个Yii应用1、进入您网站更目录2、执行命令:YiiRoot/framework/yiicwebapptestdrive说明:这里的YiiRoot为您Yii框架的安装目录。3、输入以上命令后,会出现一个提示信息:PHPWarning:PHPStartup:Unabletol
一、ThinkPHPThinkPHP(FCS)是一个轻量级的中型框架,是从Java的Struts结构移植过来的中文PHP开发框架。它使用面向对象的开发结构和MVC模式,并且模拟实现了Struts的标签库,各方面都比较人性化,熟悉J2EE的开发人员相对比较容易上手,适合php框架初学者。ThinkPHP的宗旨是简化开发、提
我必须实现标题中提到的验证,即需要两个字段之一(电子邮件,电话).我在我的模型中这样做:[['email'],'either',['other'=>['phone']]],这是方法:publicfunctioneither($attribute_name,$params){$field1=$this->getAttributeLabel($attribute_nam
我试图得到(StatusCode)响应RESTapi,而它只返回字段名称和错误消息,如下所示[{"field":"Email","message":"Email\"ali@ali.ali\"hasalreadybeentaken."}]我添加了回复'response'=>['class'=>'