yii2 Url 自定义 伪静态url

这里说的伪静态url,其实就是自定义url,

譬如:www.fancyecommerce.com/fashion-handbag-women.html

这个urlkey   对应的fashion-handbag-women.html 是没有这个文件的。但是为了seo,需要把url改成这个样子,也就是url自定义,这个,我们需要保存这个url到数据库,对应一个yii2中的urlPath以及对应的参数。

譬如在数据库中保存:fashion-handbag-women.html 对应 /report/order/index?sort=id&p=3

当访问www.fancyecommerce.com/fashion-handbag-women.html这个url的时候,实际加载的是www.fancyecommerce.com/report/order/index?sort=id&p=3。

现在说的是实现思路:

在入口文件,我们可以看到:

$application = new yii\web\Application($config);
$application->run();

 

查找run方法:yii\base\Application

public function run()
    {
        try {

            $this->state = self::STATE_BEFORE_REQUEST;
            $this->trigger(self::EVENT_BEFORE_REQUEST);

            $this->state = self::STATE_HANDLING_REQUEST;
            $response = $this->handleRequest($this->getRequest());

            $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);
            return $e->statusCode;

        }
    }

在这里我们可以看到代码

$response = $this->handleRequest($this->getRequest());

然后查找方法:

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);
        }
    }

上面的代码第四行为resolue方法,我们去yii\web\Request查看该方法

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

然后我们去yii\web\UrlManager中查看。parseRequest()

public function parseRequest($request)
    {
        if ($this->enablePrettyUrl) {
            $pathInfo = $request->getPathInfo();

也就找到代码  $pathInfo = $request->getPathInfo()方法,如下:

public function getPathInfo()
    {
        if ($this->_pathInfo === null) {
            $this->_pathInfo = $this->resolvePathInfo();
        }

然后我们找到resolvePathInfo方法,如下:

protected function resolvePathInfo()
    {
        $pathInfo = $this->getUrl();

找到getUrl方法,如下:

public function getUrl()
    {
        if ($this->_url === null) {
            $this->_url = $this->resolveRequestUri();
        }

        return $this->_url;
    }

找到resolveRequestUri方法,如下:

protected function resolveRequestUri()
    {
        if (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // IIS
            $requestUri = $_SERVER['HTTP_X_REWRITE_URL'];
        } elseif (isset($_SERVER['REQUEST_URI'])) {
            $requestUri = $_SERVER['REQUEST_URI'];
            if ($requestUri !== '' && $requestUri[0] !== '/') {
                $requestUri = preg_replace('/^(http|https):\/\/[^\/]+/i', '', $requestUri);
            }
        } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0 CGI
            $requestUri = $_SERVER['ORIG_PATH_INFO'];
            if (!empty($_SERVER['QUERY_STRING'])) {
                $requestUri .= '?' . $_SERVER['QUERY_STRING'];
            }
        } else {
            throw new InvalidConfigException('Unable to determine the request URI.');
        }

        return $requestUri;
    }

到这里,我们基本找到根源了,我们可以在这里插入代码,但是我们不能直接修改源码,所以,我们需要新建一个class,然后通过配置修改:

二:详细的代码:component中加入组件

'request' => [
      'class' => 'common\web\Request',
      'enableCookieValidation' => true,
      'enableCsrfValidation' => true,
      'cookieValidationKey' => 'O1d232trde1x-M97_7QvwPo-5QGdkLMp#@#@',
      'noCsrfRoutes' => [
        'catalog/product/addreview',
                'favorite/product/remark',
        'paypal/ipn/index',
        'paypal/ipn',
      ],
    ],

创建文件common\web\Request

protected function resolveRequestUri()
    {
        if (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // IIS
            $requestUri = $_SERVER['HTTP_X_REWRITE_URL'];
        } elseif (isset($_SERVER['REQUEST_URI'])) {
            $requestUri = $_SERVER['REQUEST_URI'];
            if ($requestUri !== '' && $requestUri[0] !== '/') {
                $requestUri = preg_replace('/^(http|https):\/\/[^\/]+/i', '', $requestUri);
            }
        } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0 CGI
            $requestUri = $_SERVER['ORIG_PATH_INFO'];
            if (!empty($_SERVER['QUERY_STRING'])) {
                $requestUri .= '?' . $_SERVER['QUERY_STRING'];
            }
        } else {
            throw new InvalidConfigException('Unable to determine the request URI.');
        }
    # 修改代码如下:
    # return $requestUri;
    # 改为:
    return $this->getRewriteUri($requestUri);
    }

定义getRewriteUri方法:代码如下:

##重写url ,根据得到的url,在 $rewrite_url_arr 中查找是否存在 ,如果存在,
  ##说明这个url是自定义的url,需要更改成真实的url, 更改RequestUri为原来的url
  protected function getRewriteUri($requestUri){
    $front_requestUri = "";
    $wh_requestUri = "";
    $dh_requestUri = "";
    if(strstr($requestUri,"?")){
      $arr = explode("?",$requestUri);
      $front_requestUri = $arr[0];
      $wh_requestUri = $arr[1];
    }else if(strstr($requestUri,"#")){
      $arr = explode("#",$requestUri);
      $front_requestUri = $arr[0];
      $dh_requestUri = $arr[1];
    }else{
      $front_requestUri = $requestUri;
    }
    //echo $requestUri;exit;
    if($custom_uri = $this->getCustomUrl($front_requestUri)){
      if($wh_requestUri){
        return $custom_uri."?".$wh_requestUri;
      }else if($dh_requestUri){
        return $custom_uri."#".$dh_requestUri;
      }else{
        return $custom_uri;
      } 
    }else{
      return $requestUri;
    }
    
  }
  #根据当前的自定义uri,得到数据库保存的真实uri。
  protected function getCustomUrl($uri){
    # 去掉头部的/
    if(substr($uri,0,1) == "/"){
      $uri = substr($uri,1);
    }
    $url_rewrite_coll = \Yii::$app->mongodb->getCollection('url_rewrite');
    $one = $url_rewrite_coll->findOneConvert(['request_path' => $uri]);
    if($one['_id']){
      $type = $one['type'];
      $type_data_id = $one['type_data_id'];
      Global $page_handle;
      if($type == 'product'){
        $product_coll = \Yii::$app->mongodb->getCollection("catalog_product");
        $where = ["_id"=>(int)$type_data_id,"status"=>1 ];
        if(!Config::param("out_stock_product_is_show")){
          $where['is_in_stock'] = 1;
        }
        $product_data = $product_coll->findOneConvert($where);
        if($product_data['_id']){
          $page_handle = $product_data;
          return '/catalog/product/index';
        }
      }else if($type == 'category'){
        $category_table = "catalog_category";
        $category_coll = \Yii::$app->mongodb->getCollection($category_table);
        
        $category_data = $category_coll->findOneConvert(["_id"=>(int)$type_data_id,"status"=>1 ]);
        if($category_data['_id']){
          $page_handle = $category_data;
          return '/catalog/category/index';
        }
      }else if($type == 'cmspage'){
        $cmspage_coll = \Yii::$app->mongodb->getCollection("cms_page");
        $cmspage_data = $cmspage_coll->findOneConvert(["_id"=>(int)$type_data_id,"status"=>1 ]);
        if($cmspage_data['_id']){
          $page_handle = $cmspage_data;
          return '/home/index/page';
        }
      # 下一步做。blog没有做。
      }else if($type == 'blog'){
        $blog_coll = \Yii::$app->mongodb->getCollection("blog_article");
        $blog_data = $blog_coll->findOneConvert(["_id"=>(int)$type_data_id,"status"=>1 ]);
        if($blog_data['_id']){
          $page_handle = $blog_data;
          return '/blog/blog/index';
        }
      }else if($type == 'blogcategory'){
        $blogcategory_coll = \Yii::$app->mongodb->getCollection("blog_category");
        $blogcategory_data = $blogcategory_coll->findOneConvert(["_id"=>(int)$type_data_id ]);
        if($blogcategory_data['_id']){
          $page_handle = $blogcategory_data;
          return '/blog/category/index';
        }
      }else{
        return false;
      }
    }else{
      $rewrite_url_arr = array(
        'contacts'=>'customer/contacts/index',
      );
      if($rewrite_url_arr[$uri]){
        return "/".$rewrite_url_arr[$uri];
      }
      return false;
    }
    
    
    
  }

yii2 自定义 Url ,到这里基本已经说完, 关于yii2的 伪静态url,还需要在nginx哪里做设置:

当然,我的这个定义,是按照我自己的逻辑来的,大家可以根据自己的方式来

为了加速,这个部分最好是放到redis里面,快速查询。

发表评论

电子邮件地址不会被公开。 必填项已用*标注