yii2 请求处理过程解析

所有的迷惑都会在源码中得到解答
来一浏览器的请求发送到yii时是如何被变更为对应的controller=>action进行处理的呢??
一言不合上代码,清除处理主要在web\application类中处理的


public function handleRequest($request)
{
    if (empty($this->catchAll)) {
        list ($route, $params) = $request->resolve();
    } else {
        $route = $this->catchAll[0];
        $params = $this->catchAll;
        unset($params[0]);
    }
    try {
        Yii::trace("Route requested: '$route'", __METHOD__);
        $this->requestedRoute = $route;
        $result = $this->runAction($route, $params);
        if ($result instanceof Response) {
            return $result;
        } else {
            $response = $this->getResponse();
            if ($result !== null) {
                $response->data = $result;
            }

            return $response;
        }
    } catch (InvalidRouteException $e) {
        throw new NotFoundHttpException(Yii::t('yii', 'Page not found.'), $e->getCode(), $e);
    }
}

而对于解析则是在$request->resolve当中进行的

public function resolve()
{
    $result = Yii::$app->getUrlManager()->parseRequest($this);

    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()];
    } else {
        throw new NotFoundHttpException(Yii::t('yii', 'Page not found.'));
    }
}

看到了吧,还得继续跟,解析是在parseRequest中进行的,这个parseRequest函数很长,不过我们不用看前半部分哈哈

public function parseRequest($request)
{
    if ($this->enablePrettyUrl) {
        $pathInfo = $request->getPathInfo();
        /* @var $rule UrlRule */
        foreach ($this->rules as $rule) {
            if (($result = $rule->parseRequest($this, $request)) !== false) {
                return $result;
            }
        }

        if ($this->enableStrictParsing) {
            return false;
        }

        Yii::trace('No matching URL rules. Using default URL parsing logic.', __METHOD__);

        // Ensure, that $pathInfo does not end with more than one slash.
        if (strlen($pathInfo) > 1 && substr_compare($pathInfo, '//', -2, 2) === 0) {
            return false;
        }

        $suffix = (string) $this->suffix;
        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;
            }
        }

        return [$pathInfo, []];
    } else {
        Yii::trace('Pretty URL not enabled. Using default URL parsing logic.', __METHOD__);
        //我们需要看的就这一点了!!!
        $route = $request->getQueryParam($this->routeParam, '');
        if (is_array($route)) {
            $route = '';
        }

        return [(string) $route, []];
    }
}

就快要到了,这里需要mark一下,注意传递进去的参数是$this->routeParam就是"r"看下getQueryParam函数的处理

public function getQueryParam($name, $defaultValue = null)
{
    $params = $this->getQueryParams();
    return isset($params[$name]) ? $params[$name] : $defaultValue;
}
public function getQueryParams()
{
    if ($this->_queryParams === null) {
        return $_GET;
    }
    return $this->_queryParams;
}
好了,终于跟到底了,发现了吗?getQueryParam做了什么???就是把$_GET请求中明为$this->touteParam的参数取了出来!!!!!
其实取得就是$_GET['r'] 这一层层跟的火大。
返回的值就是site/login这下知道了吧
好了,继续看handleRequest还没执行完呢,接下来看的是web\application的runAction,传递进去的参数就是site\login
public function runAction($route, $params = [])
{
    $parts = $this->createController($route);
    if (is_array($parts)) {
        /* @var $controller Controller */
        list($controller, $actionID) = $parts;
        $oldController = Yii::$app->controller;
        Yii::$app->controller = $controller;

        $result = $controller->runAction($actionID, $params);

        Yii::$app->controller = $oldController;

        return $result;
    } else {
        $id = $this->getUniqueId();
        throw new InvalidRouteException('Unable to resolve the request "' . ($id === '' ? $route : $id . '/' . $route) . '".');
    }
}

继续看,这个createController
public function createController($route)
{
    if ($route === '') {
        $route = $this->defaultRoute;
    }


    // 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])) {
        //如果在controllerMap中定义了该controller Id,则直接创建对应的对象,也即r对应的值不一定是controller的类的名字
        $controller = Yii::createObject($this->controllerMap[$id], [$id, $this]);
        return [$controller, $route];
    }
    $module = $this->getModule($id);
    if ($module !== null) {
        return $module->createController($route);
    }

    if (($pos = strrpos($route, '/')) !== false) {
        $id .= '/' . substr($route, 0, $pos);
        $route = substr($route, $pos + 1);
    }

    $controller = $this->createControllerByID($id);
    if ($controller === null && $route !== '') {
        $controller = $this->createControllerByID($id . '/' . $route);
        $route = '';
    }

    return $controller === null ? false : [$controller, $route];
}
返回的是controller对象和actionId,前两个if就是判断合法性,第三个if将字符串进行了根据/进行了分离 $id  ="site"  $route="login"
如果controllerMap中没有定义key的'site'的配置,这里可以由我们自己进行处理,那么就使用siteController类作为本次处理的controller,而$route则是action的操作了返回之后再module的runAction当中的runAction是调用创建的controller的runAction,这一部分就是我们自己编写的处理过程了




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

世纪殇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值