YII URL管理教程,摆脱?r=xxxx/xxxx,实现伪静态

Web应用程序完整的URL管理包括两个方面。首先, 当用户请求约定的URL,应用程序需要解析它变成可以理解的参数。第二,应用程序需要提供一种创造URL的方法,可以让创建的URL应用程序正确理解。对于Yii应用程序,这些通过CUrlManager辅助完成。

Creating URLs(创建网址)

虽然URL可被硬编码在控制器的视图(view)文件,但动态的创建他们会更加灵活:

$url=$this->createUrl($route,$params);

$this指的是控制器实例; $route指定请求的route 的要求;$params 列出了附加在网址中的GET参数。

默认情况下,URL以get格式使用createUrl 创建。例如,提供$route='post/read'$params=array('id'=>100) ,我们将获得以下网址:

/index.php?r=post/read&id=100

参数以一系列Name=Value通过符号串联起来出现在请求字符串,r参数指的是请求的route 。这种URL格式用户友好性不是很好,因为它需要一些非单词字符。

我们可以使上述网址看起来更简洁,更不言自明,通过采用所谓的 path 格式,省去查询字符串并把GET参数加到路径信息,作为网址的一部分:

/index.php/post/read/id/100

要更改URL格式,我们应该配置urlManager应用组件,以便createUrl可以自动切换到新格式,并可以让应用程序可以正确理解新的网址:

array(
    ......
    'components'=>array(
        ......
        'urlManager'=>array(
            'urlFormat'=>'path',
        ),
    ),
);

请注意,我们不需要指定的urlManager元件的类,因为它在CWebApplication预声明为CUrlManager。

提示:此网址通过createurl方法所产生的是一个相对地址。为了得到一个绝对的url ,我们可以用前缀yii::app()->hostInfo ,或调用createAbsoluteUrl 。

User-friendly URLs(用户友好的URL)

当用path作为URL格式,我们可以指定某些URL规则使我们的网址对用户更加友好性。例如,我们可以产生一个短短的 URL/post/100 ,而不是冗长/index.php/post/read/id/100。网址创建和解析都是通过CUrlManager指定网址规则。

要指定的URL规则,我们必须设定urlManager 应用组件的属性rules:

array(
    ......
    'components'=>array(
        ......
        'urlManager'=>array(
            'urlFormat'=>'path',
            'rules'=>array(
                'pattern1'=>'route1',
                'pattern2'=>'route2',
                'pattern3'=>'route3',
            ),
        ),
    ),
);

规则被指定为一个由pattern-route pairs组成的数组,每一个对应一个规则。一个规则的 pattern 是一个字符串,用来匹配 URL的路径信息部分(the path info part of URLs)。一个规则的route应当指向一个有效的控制器路由。

除了上面的 pattern-route 格式,一个规则也可以以自定义选项来指定,如下:

’pattern1’=>array(’route1’, ’urlSuffix’=>’.xml’, ’caseSensitive’=>false)

在上面,数组包含一个自定义选项列表。从版本 1.1.0 起,下面的选项可用:

  • urlSuffix: 此规则使用的 URL 后缀。默认是 null ,意味着使用 CUrlManager::urlSuffix 的值。
  • caseSensitive: 是否规则区分大小写。默认是 null,意味着使用 CUrlManager::caseSensitive 的值。
  • defaultParams: 此规则提供的默认 GET 参数(name=>value)。When this rule is used to parse the incoming request, the values declared in this property will be injected into GET
  • matchValue : whether the GET parameter values should match the corresponding sub patterns in the rule when creating a URL. Defaults to null, meaning using the value of CUrlManager::matchValue.If this property is false, it means a rule will be used for creating a URL if its route and parame patterns.Note that setting this property to true will degrade performance.

使用命名参数(Using Named Parameters)

规则可以绑定少量的GET参数。这些出现在规则格式的GET参数,按照如下的特殊格式:

ParamName表示GET参数名字,可选项ParamPattern表示将用于匹配 GET参数值的正则表达式。如果省略了ParamPattern,表示该参数匹配除了/. 之外的任何字符。当生成一个网址(URL)时,这些参数将被相应的参数值替换;当解析一个网址时,相应的GET参数将通过解析结果来生成。

我们使用一些例子来解释URL规则如何工作。我们假设我们的规则包括如下三个:

array(
    'posts'=>'post/list',
    'post/<id:\d+>'=>'post/read',
    'post/<year:\d{4}>/<title>'=>'post/read',
)
  • 调用$this->createUrl('post/list')生成/index.php/posts。第一个规则适用。
  • 调用$this->createUrl('post/read',array('id'=>100))生成/index.php/post/100。第二个规则适用。
  • 调用$this->createUrl('post/read',array('year'=>2008,'title'=> 'a sample post'))生成/index.php/post/2008/a sample post。第三个规则适用。
  • 调用$this->createUrl('post/read')产生/index.php/post/read。请注意,没有规则适用。

也就是说,当使用createUrl生成URL,路由(route )和传递给该方法的GET参数被用来决定哪些URL规则适用。如果规则中的每个相关参数可以在被传递给createUrl的GET参数中找到的,并且路由的规则也匹配路由参数,规则将用来生成网址。

如果传递到createUrl的GET参数比规则这种给出的参数要多,俺么其他参数将出现在查询字符串。例如,如果我们调用$this->createUrl('post/read',array('id'=>100,'year'=>2008)) ,我们将获得

/index.php/post/100?year=2008

为了使这些额外参数出现在路径信息的一部分,我们应该给规则附加/* 。 因此,使用规则post/<id:\d+>/* ,我们可以获取网址

/index.php/post/100/year/2008

正如我们提到的,URL规则的另一个用途是解析请求网址。当然,这是URL生成的一个逆过程。例如, 当用户请求==/index.php/post/100==,上面例子的第二个规则将适用来解析路由post/read和 GET参数array('id'=>100) (可通过$_GET获得) 。

注意:使用URL rule 会降低系统性能,这是因为解析一个URL请求的时候,CUrlManager 会尝试用每一个rule进行匹配,直到有一个符合,ruler的数量越多,性能的开销越大,因此高流量的网站应该尽量减少URL ruler的应用。

参数化路由

从1.0.5版本开始,我们可以在ruler中对路由路径参数化。这允许一条ruler可以应用到多条相匹配路由。这也有利于减少应用ruler的数量,提高整体性能。

我们使用下面的例子来解释如何使用命名参数对路由进行参数化

array(
    '<_c:(post|comment)>/<id:\d+>/<_a:(create|update|delete)>' => '<_c>/<_a>',
    '<_c:(post|comment)>/<id:\d+>' => '<_c>/read',
    '<_c:(post|comment)>s' => '<_c>/list',
)

在上面,我们在ruler的路由部分使用了两个命名参数_c 和 _a,前者匹配一个控制器id是post或者comment,后者匹配一个动作id是create、update或者delete。你可以把参数的名字起的尽可能长,以避免和出现在GET中的参数冲突。

使用上面的规则URL /index.php/post/123/create,会被解释为post/create,并具有GET参数id=123。给出路由comment /list 和GET参数page=2,我们可以创建URL /index.php/comments?page=2

参数化主机名

从1.0.11版本开始,分析和创建URLs的rule中可以支持主机名。一方面,可以读取路径中的主机名作为GET变量,例如:地址 http://admin.example.com/en/profile,可以被解析为GET 变量 user=admin 和 lang=en。另一方面,开主机名的ruler可以创建参数化主机名的URLs

为了使用参数化的主机名,我们可以用主机信息声明URL rules,例如:

array(
    'http://<user:\w+>.example.com/<lang:\w+>/profile' => 'user/profile',
)

上面的例子表示,主机名的第一部分被当做user参数,而第二部分被当做lang参数,相符合的路由是user/profile路由。

请注意 当URL是由参数化的主机来创建时,CUrlManager::showScriptName不会起作用。

同样需要注意如果应用是在WEB根目录的子文件夹底下,参数化主机名的ruler不能包含子文件夹,例如,如果应用的路径是在 http://www.example.com/sandbox/blog下面,我们可以仍然使用和上面描述相同的URL ruler:sandbox/blog 而不需要子文件夹

隐藏 index.php

还有一点,我们可以进一步清理我们的网址,即在URL中藏匿index.php入口脚本。这就要求我们配置Web服务器,以及urlManager应用程序元件。

我们首先需要配置Web服务器,这样一个URL没有入口脚本仍然可以由入口脚本来处理。如果是Apache HTTP server ,可以通过打开网址重写引擎和指定一些重写规则。这两个操作可以在包含入口脚本的目录下的.htaccess文件里实现。下面是一个示例:

Options +FollowSymLinks
IndexIgnore <em>/</em>
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

然后,我们设定urlManager元件的showScriptName属性为 false。

现在,如果我们调用$this->createUrl('post/read',array('id'=>100)) ,我们将获取网址/post/100 。更重要的是,这个URL可以被我们的Web应用程序正确解析。

Faking URL Suffix(伪造URL后缀)

我们还可以添加一些网址的后缀。例如,我们可以用/post/100.html来替代/post/100 。这使得它看起来更像一个静态网页URL。为了做到这一点,只需配置urlManager组件的urlSuffix属性为你所喜欢的后缀。

参考:http://www.yiiframework.net/post/85/URL管理

若您觉得我的博文对您有帮助,欢迎点击下方按钮对我打赏
打赏