码迷,mamicode.com
首页 > 其他好文 > 详细

Yii 2.0.6 - 从入口到Action执行

时间:2019-02-13 12:22:02      阅读:145      评论:0      收藏:0      [点我收藏+]

标签:gis   2.0   before   efi   formatter   iso   pac   ttyu   null   

 

 

 

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__)); // 注册别名
{
    \yii\BaseYii::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 \yii\BaseYii
    {
    }

    spl_autoload_register([‘Yii‘, ‘autoload‘], true, true); // 注册类加载器
    \yii\BaseYii::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); // 通过别名获取
            {
                \yii\BaseYii::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 [
          ‘yii\base\Action‘ => YII2_PATH . ‘/base/Action.php‘,
          ‘yii\base\ActionEvent‘ => YII2_PATH . ‘/base/ActionEvent.php‘,
          ‘yii\base\ActionFilter‘ => YII2_PATH . ‘/base/ActionFilter.php‘,
          ‘yii\base\Application‘ => YII2_PATH . ‘/base/Application.php‘,
          ‘yii\base\ArrayAccessTrait‘ => YII2_PATH . ‘/base/ArrayAccessTrait.php‘,
          ‘yii\base\Arrayable‘ => YII2_PATH . ‘/base/Arrayable.php‘,
        ];
    }

    Yii::$container = new yii\di\Container();
}



$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;

        }
    }
}

  

Yii 2.0.6 - 从入口到Action执行

标签:gis   2.0   before   efi   formatter   iso   pac   ttyu   null   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!