1. 程式人生 > >[路由] -- Yii2 url地址美化與重寫

[路由] -- Yii2 url地址美化與重寫

第一個教程

目的:我只想去掉瀏覽器位址列中的index.php?r=這一塊。

在/config/web.php中 ’components'=>[] 中新增如下程式碼:

複製程式碼
1 'urlManager' => [
2             'enablePrettyUrl' => true,
3             'showScriptName' => false,//隱藏index.php 
4             //'enableStrictParsing' => false,
5             'suffix' => '.html',//
字尾,如果設定了此項,那麼瀏覽器位址列就必須帶上.html字尾,否則會報404錯誤 6 'rules' => [ 7 //'<controller:\w+>/<action:\w+>'=>'<controller>/<action>', 8 ], 9 ],
複製程式碼

如果帶了改了字尾這一下,請記得一定要給瀏覽器位址列的路徑最後面加上.html。

改了以上這些,我發現?r=這塊可以用/代替訪問了,但是想隱藏掉index.php還是不行。

我們還需在index.php同級的目錄下新增.htaccess檔案:

開啟記事本,輸入以下程式碼:

1 2 3 4 5 6 7 8 9 10 Options +FollowSymLinks IndexIgnore */* RewriteEngine on # if a directory or a file exists, use it directly RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d # otherwise forward it to index.php RewriteRule . 
index.php

然後儲存在與入口檔案index.php同級的目錄下,也就是/web目錄下,檔名自己填.htaccess,檔案型別選擇 所有檔案 (*.*) ,然後儲存即可。

最後測試OK了!

第二個教程

何為美化路由呢?美化嘛,無外乎就是給路由化化妝,讓她好看點。我雖沒化過妝,那好歹也是見過描描眉的。下面我們就來看看如何給你的路由新增新增點“顏色”的。

yii的路由美化工作,全權由urlManager元件負責。預設情況下,該元件並沒有開啟。

我們在配置檔案backend\config\main.php中簡單配置下該元件

'urlManager' => [
    'enablePrettyUrl' => false,
    'showScriptName' => true,
    'enableStrictParsing' => false,
    'suffix' => '',
    'rules' => [
    ],
],

按照我們上文的配置,你可能看不到當前路由有什麼變化,我們來做幾個小例子分別講述下要介紹的這幾個引數

enablePrettyUrl:是否開啟美化效果

我們把false改為true前後,分別訪問下左側的“部落格”選單項,前後對比如下:

false:/index.php?r=blog%2Findex
true:/index.php/blog/index

這效果感覺跟開了美顏相機似的。

showScriptName:是否或略指令碼名index.php

就上面的連結而言,大多數情況下我們並不想展示index.php,我們更想要的是/blog/index效果,這個時候showScriptName的作用就顯現出來了

不過該引數還需要我們配置web伺服器如apache和nginx,為了更詳細的說明,我們準備單獨寫篇文章說說。

enableStrictParsing:是否開啟嚴格解析路由

什麼意思呢?假設我們在開啟了路由美化的功能(enablePrettyUrl設定為true),enableStrictParsing設定為false的情況下,我們直接訪問/index.php/blog/index肯定是沒有問題的。但是如果我們直接訪問/index.php?r=blog%2Findex呢?發現頁面展示的效果是/site/index(實際上這裡展示的預設的路由頁面),並非是部落格列表頁面。如果我們把enableStrictParsing引數設定為true你會發現頁面直接丟擲404。因為這貨設定為true之後,會匹配rules選項中設定的至少一個規則,那我們這裡先設定一個路由,不然沒法繼續了。

'rules' => [
    "<controller:\w+>/<action:\w+>"=>"<controller>/<action>",
],

此時重新整理下/index.php/blog/index就正常了。

rules:包含了路由的匹配規則列表

也就是說,如果我們要定製特殊的路由,就需要通過這個屬性進行配置。

rules包含著我們配置的路由規則列表,當解析一個路由或者生成一個路由的時候,匹配規則的順序是從第一條規則開始,知道匹配到第一個滿足的為止。

我們來說一下rules的每一項的規則,以/blogs為例,當然這是一個不存在的路由,你可以訪問下試試會不會丟擲404異常。

我們在rules的第一項新增,現在我們的rules是下面這樣的

'rules' => [
    '/blogs' => '/blog/index',
    "<controller:\w+>/<action:\w+>"=>"<controller>/<action>",
],

這其實就是把我們訪問的/blogs路由對映到/blog/index路由上面了,所以我們訪問/blogs才得以被解析並能正常訪問/blog/index頁面。

我們再舉一個例子,如果我們要求訪問/blogs/1可以展示/blog/view?id=1這個介面呢?

實際上/blog/view?id=1需要一個引數是id,我們可以這樣做一個對映

'/blogs/<id:\d+>' => '/blog/view',

可以自行體會一下。

但是,如果我們的專案要求所有的路由都這樣被解析,每一個都這樣寫rules豈不是很龐大很複雜?

rules不只支援正則匹配,我們還可以配置controller和action匹配所有滿足的路由。比如我們在開啟enableStrictParsing為true後,設定的

"<controller:\w+>/<action:\w+>"=>"<controller>/<action>",

再比如如果我們想要所有的controller/id對映到controller/view介面,我們可以這樣配置

'rules' => [
    '/blogs' => '/blog/index',
    // '/blogs/<id:\d+>' => '/blog/view',
    '<controller:\w+>/<id:\d+>' => '<controller>/view',
    "<controller:\w+>/<action:\w+>"=>"<controller>/<action>",
],

此時我們訪問 /index.php/blog/1 會正常顯示/blog/view?id=1這個介面。

suffix:url字尾

有時候我們想要訪問的頁面都帶上.html字尾,這個時候只需要簡單的配置suffix引數即可

'suffix' => '.html',

如果我們此時在訪問/index.php/blog/index恐怕是不可以的,因為我們已經要求所有的url字尾都要帶上.html才可以被正常解析!即只有訪問 /index.php/blog/index.html 才是可以的。

urlManager的匹配規則我們掌握了,但是!整個網站的連結是要我們手動寫的,難不成你天天修改規則,我還要天天修改連結的寫法嗎?這簡直就是一場“災難”!

舉一個例子,由於網站前期並沒有考慮頁面路由新增.html字尾利於seo搜尋的問題,小張三,哦不小張,名字有點lower,小三吧,哦不還是小張吧。小張整站的連結的寫法都是這樣的

<a href="/site/index">Yii Forum &raquo;</a>
<a href="/site/index2">Yii Forum2 &raquo;</a>
<a href="/site/index3">Yii Forum3 &raquo;</a>

固定死的寫法,這無異於給自己埋了一顆定時炸彈!

有一天老大說了,要求我們網站所有的連結都加字尾.html。no zuo no die!

再來一個小練習考考各位:

一般情況下,我們的後臺列表的資料分頁是藉助yii\data\Pagination生成的,正常情況下其連結是這樣的

/blog/index?page=2

如果我們想要的連結是下面這種形式的,請問如何設計?

// 其中 2是具體分頁的頁面
/blog/index/2.html

這個例子具體典型性,請一定要先思考再繼續看下面答案!

你是不是沒思考,請先思考後動手嘗試幾種方案後再繼續往下閱讀!

來,我們公佈看看這個案例如何解決

列表頁的資料我們是通過gridview進行展示的,但資料的來源,是通過BlogSearch的search方法提供的,我們看下這個search方法,發現最終提供資料的是ActiveDataProvider例項,這個ActiveDataProvider厲害了,它還集成了分頁類yii\data\Pagination。只需要通過ActiveDataProvider的pagination屬性便可以配置分頁類。具體的分頁基礎可以參考這篇文章

我們的blog表暫時沒那麼多資料,為了分頁效果我們暫時設定pageSize為2,這裡並設定每頁數量的引數為false

$dataProvider = new ActiveDataProvider([
    'query' => $query,
    'pagination' => [
        'pageSize' => 2,
        'pageSizeParam' => false,
    ],
]);

接下來我們要做的,便是配置urlManager的路由規則,以便生成的連結滿足我們的需求。

在rules中新增一條如下的規則即可

'<controller:\w+>/<action:\w+>/<page:\d+>' => '<controller>/<action>',

完整版的如下:

'urlManager' => [
    'enablePrettyUrl' => true,
    'showScriptName' => false,
    'enableStrictParsing' => true,
    'suffix' => '.html',
    'rules' => [
        '<controller:\w+>/<action:\w+>/<page:\d+>' => '<controller>/<action>',
        "<controller:\w+>/<action:\w+>"=>"<controller>/<action>",
    ],
],

Url工具類的使用

URL工具類實際上只的是yii\helpers\BaseUrl類,實際寫所有連結的時候,我們建議通過該類來生成連結,其好處不可言喻。

如果小張所有的連結都像下面這樣寫,反過來想想,他準能幸福的屁顛屁顛的。

use yii\helpers\Url;
<a href="<?= Url::to(['site/index']) ?>">Yii Forum &raquo;</a>
<a href="<?= Url::toRoute('site/index') ?>">Yii Forum2 &raquo;</a>
<a href="<?= Url::toRoute(['site/index']) ?>">Yii Forum3 &raquo;</a>

細心的同學發現了我們這裡其實列舉了三種寫法,其效果都是一樣的。尤其是使用Url::to方法,引數一定要是屬組形式,屬組形式的引數等同於Url::toRoute的效果。

我們的重心就轉移到Url::toRoute方法上面了。該方法會根據你配置的urlManager元件去生成連結,按照我們上文中對urlManager的配置,我們再來列舉兩個簡單的案例

<a href="<?= Url::to(['/blogs']) ?>">Yii Forum4 &raquo;</a>
<a href="<?= Url::to(['site/index', 'id' => 1]) ?>">Yii Forum5 &raquo;</a>

其生成的連結形式分別是

<a href="/index.php/blogs.html">Yii Forum4 »</a>
<a href="/index.php/site/index/1.html">Yii Forum5 »</a>

關於路由的美化與連結的生成,我們就說這麼多,尤其是連結的生成需要特別注意哦,no zuo no die!