这里说的伪静态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里面,快速查询。