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