多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
![](https://box.kancloud.cn/c30c32377ecaf76611c1f31be8b28c01_602x733.png) ![](https://box.kancloud.cn/e38b826959f77d0062a339f01a805ac7_440x98.png) ![](https://box.kancloud.cn/c8f9fcb6574897cf200351c26550339c_714x330.png) 一般情况下,Yii应用生成和接受形如`http://www.domain.com/index.php?r=post/view&id=1`的URL。这个URL分成几个部分: * 表示主机信息的`http://www.domain.com` * 表示入口脚本的`index.php` * 表示路由的`r=post/view` * 表示普通查询参数的`id=1` **隐藏入口文件** * Nginx位置 ~~~ location / { try_files $uri $uri/ /index.php?$args; } ~~~ * Apache配置文件(放在入门文件同级目录) ~~~ RewriteEngine on # 如果是一个目录或者文件,就访问目录或文件 RewriteCond %{REQUEST_FILENAME} !-d # 如果文件存在,就直接访问文件,不进行下面的RewriteRule RewriteCond %{REQUEST_FILENAME} !-f RewriteRule . index.php ~~~ > 另外服务器需要开启`rewrite`模块。 **配置UrlManager组件** 打开`@app/config/main.php`中的`components`下面添加以下代码,如果想在全局生效可以将配置直接写入`common`模块下 ~~~ 'components'=>[ ... 'urlManager' => [ 'enablePrettyUrl' => true, 'showScriptName' => false, 'suffix' => '.html', // 伪后缀 'rules'=>[ 'article/<id:\d+>' => 'article/view', // 文章详情 'articles/<country_id:\d+>' => 'article/index', // 文章列表 ], ], ... ], ~~~ **实现伪静态** 这是通过`urlManager`(URL管理者)这个组件来实现的,你可以先在控制器里var\_dump一下`Yii::$app->urlManager`这个组件,它是Yii的核心组件 框架默认情况下是没有开启伪静态URL的,我们需要修改一下urlManager组件的配置来开启伪静态 在配置里增加`urlManager`组件的配置,注意值是一个数组哦!因为我们要控制一些组件属性的值嘛 至于这个组件都有什么属性呢,详细需要参考官方的urlManager组件的对应类的说明[yii\\web\\UrlManager](http://www.yiichina.com/doc/api/2.0/yii-web-urlmanager) 而咱们要实现伪静态只需要知道几个属性:`enablePrettyUrl`、`showScriptName`、`enableStrictParsing`、`rules`这四个属性! 请按照我下面这样来配置urlManager组件: ~~~php 'urlManager' => [ 'enablePrettyUrl' => true, //开启伪静态URL模式 'showScriptName' => false, //生成的网址里不带入口脚本名称 'enableStrictParsing' => true, //开启严格伪静态模式 'rules' => [ //伪静态规则配置,下面会讲解如何填写 ], ], ~~~ 好了,估计`?r=test/abc`这样的URL一旦访问时就会找不到页面而报404错误了,说明已经成功开启了伪静态模式 接下来我们添加一个URL白名单让它路由到test控制器的abc方法 上面增加urlManager组件的配置后,里面有个rules属性,值是一个数组,这里就是放URL白名单的地方了 比如我们要实现`/uiui.html`这个网址访问到test控制器的abc方法,就这样添加rules内容: ~~~php 'rules' => [ 'uiui.html' => 'test/abc', ], ~~~ 神奇的事发生了!当你在浏览器输入“\*\**[http://xxx.com/uiui.html](http://xxx.com/uiui.html)*” 就会运行test控制器abc方法的代码 然后你试着在控制器里`echo Url::to(['test/abc']);`也会输出“**/uiui.html**” 这个结果! 再来,你在rules里面将规则改成`'baba.html' => 'test/abc'`那Url::to方法也会将“**test/abc**”这个控制器方法标记生成为“**/baba.html**” 这就是为什么不提倡直接将网址写死在模板上的原因了,因为伪静态规则可能会在配置里被改变的,我们应该尽可能用Url::to来生成网址,减少维护的修改量 **在伪静态中传递GET参数** 我们用`/uiui.html`这样的伪静态来取代了`/?r=test/abc`的网址形式 那么又如何表达`/?r=test/abc&userId=123`呢?难道是`/uiui123.html`这样吗?不行不行 其实简单地做,就可以这样写:`/uiui.html?userId=123`,这样控制器里依然可以收到参数,不信你试试`Yii::$app->request->get('userId')` 但一般情况下我们项目中都尽量把GET参数也隐藏在伪静态之中,比如实现 `/uiui7788.html`就相当于`/?r=test/abc&userId=7788`的效果,配置办法如下: ~~~php 'rules' => [ 'uiui<userId:\d+>.html' => 'test/abc', ], ~~~ 然后你试试 ~~~php echo Url::to(['test/abc', 'userId' => 7788]); ~~~ 就能看到输出`/uiui7788.html`了 **rules的key写法简介** 这里需要一些正则表达式的知识基础,反正里面就是增加`<`和`>`这两个符号,表达这块区域要套一个参数进来 然后以参数的名称加`:`号开头,比如`userId:`这样Url::to方法的`'userId' => 值`才能知道它要生成到伪静态的哪个位置上 而`:`号后面的`\d+`表示当user\_id的值是数字的时候才可以生成,否则的话,比如`'userId' => 'abc'`这样的参数放在to方法里 由于值是字符串abc而不是一个数字,所以无法跟rules里的`\d+`(数字)匹配,不会生成预想中的`/uiuiabc.html`,如果要实现这样的话,必须将`\d+`改成`\w+`(英数字下划线),如果不熟悉正则基础的去恶补知识吧 而通常情况下rules配置中我也最常用的就是`\d+`和`\w+`这两个正则匹配符 **复杂点的多参数伪静态** 多个参数时其实也很容易理解,看看: `'uiui<userId:\d+><userName:\w+>-balabala<age:\d{2}><type:\d><width:\d+>-<height:\d+>.html' => 'test/abc'` 这里一共有6个参数,userId、userName、age、type、width和height,其中age只匹配2位数字,type只匹配一位数字 ~~~php echo Url::to(['test/abc', 'userId' => 65535, 'userName' => 'jay', 'age' => 18, 'type' => 4, 'width' => 200, 'height' => 100, ]); ~~~ 结果就生成了“**[http://xxx.com/uiui65535jay-balabala184200-100.html](http://xxx.com/uiui65535jay-balabala184200-100.html)**” 对了你有没有发现,test控制器不用建立abc方法也能生成?其实生成URL只是检查rules配置,匹配了就生成,它不管你有没有控制器方法(学过其它框架的话也很清楚,这个不新鲜了) 这个URL代入get参数后就是 ~~~php $_GET = [ 'userId' => 45678, 'userName' => 'kkqbx', 'age' => 18, 'type' => 2, 'width' => 1024, 'height' => 768, ]; ~~~ **rules的规则定义顺序** 相似的几个伪静态共存时,精确的伪静态必须放在最前面,模糊的放后面,比如有以下伪静态 ~~~php 'rules' => [ 'a<id:\w+>.html' => 'test/a', 'abc.html' => 'test/b', ] ~~~ 当访问`/abc.html`时永远不会路由到`test/b`,因为它已经被`a<id:\w+>.html`这条规则匹配成功,不再往下匹配了 想匹配test/b的话就要将`abc.html`这条规则移到test/a的规则前面才可以 重要知识点:**原则上就是越精确的伪静态就越靠前就好** 比如`abc.html`是没有正则表达式的,所以它绝对精确地描述了匹配内容,如果将带正则的规则放在前面就会被别人匹配掉了(因为正则匹配其实就是一种模糊匹配)