阿江 2017-10-05 06:10:28 5406次浏览 1条回复 3 0 0

说明

学习Yii Framework 2易2框架的过程是漫长的也是充满乐趣的以下是我学习Yii2框架时对官网英文资料(请参见原文网址)的翻译和代码实现提供了较完整的代码供你参考不妥之处请多多指正

原文网址:

http://www.yiiframework.com/doc-2.0/guide-runtime-routing.html
Routing and URL Creation(路由和创建URL)

本文主题:请求处理中的路由和创建URL(Routing and URL Creation)

1、Url Formats 2、Routing 3、Creating URLs 4、Using Pretty URLs 5、Performance Consideration

当一个Yii应用开始处理一个请求的URL时,这个URL首先会被解析成一个路由(route),然后这个路由被用于实例化对应的控制器(controller)和动作(action)以处理这个请求。这个过程被称为路由解析(routing)。 路由解析的反向过程被称为创建URL(URL creation),就是通过一个给定的路由和相关的查询参数生成一个URL。当再使用这个创建的URL进行请求时,路由解析过程将把它解析成对应的路由和请求参数。 负责路由解析和创建URL的是URL manager,它被注册为urlManager应用组件。URL manager提供了parseRequest()方法用于将一个请求解析为路由和查询参数,它还提供了createUrl()方法用于创建URL。 通过在应用中配置urlManager组件,无需改动应用中的代码,你可以让你的应用可以识别任意的URL格式,例如,你可以使用以下代码为post/view动作创建一个URL:

use yii\helpers\Url;
$url=Url::to(['post/view','id'=>100]);

依据urlManager配置的不同,生成的URL可能是以下格式(或更多)中的一种:

/index.php?r=post%2Fview&id=100
/index.php/post/100
/post/100
1、Url Formats

URL manager支持两种URL格式: 1)默认的URL格式 2)美化的URL格式 默认的URL格式使用一个名为'r'的查询参数,它代表路由参数,而其他的普通查询参数则仅代表与此路由相关的查询参数,例如:Url /index.php?r=post/view&id=100,表示路由是post/view,查询参数id是100,默认URL格式无需在Web服务器创建时对URL manager做任何配置。 美化URL格式使用紧跟入口脚本名称的扩展路径来表示路由和查询参数。例如: 扩展路径URL /index.php/post/100,/post/100或许代表路由post/view和查询参数id是100,说“或许”是因为这个路径由URL rule来决定。要使用美化URL,需要根据实际需要设计一套URL rules,它将决定URL是什么样子。 你可以通过URL manager的enablePrettyUrl属性在两种URL格式之间切换,无需对应用中的代码做任何修改。 //一个rules定义实例: D:\phpwork\advanced\common\config\main.php

//path//rules,路由规则
	'urlManager' => [
		'class' => 'yii\web\UrlManager',
		'showScriptName' => false,
		'enablePrettyUrl' => true,
		'rules' => array(
			'<controller:\w+>/<id:\d+>' => '<controller>/view',
			'<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
			'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
		),
	],
2、Routing

路由解析包括两个步骤: 1)输入的请求被解析为一个路由和查询参数; 2)与路由对应的有一个控制器和动作(controller action)被创建以处理这个请求。

当使用默认URL格式时,解析一个请求为路由非常简单,只需获取GET查询参数中的'r'值即可。 当使用美化URL格式 时,URL manager会检查注册的URL rules,匹配将这个请求解析为路由的一条规则,如果没有找到,则会抛出一个yii\web\NotFoundHttpException的异常。 一旦请求被解析为路由,就应当为这个路由创建一个控制器和动作了。路由被斜杠划分为多个部分,site/index将被分解为site和index,每个部分都是一个ID,它可以指向的是一个模块(module),一个控制器(contorller),或者是一个动作(action)。从路由的第一部分开始,应用遵循以下步骤去创建模块、控制器和动作: 1)设置当前应用为当前模块; 2)在当前模块的控制器映射表(controller map)中检查是否包含这个ID(1st ID),如果包含,将创建一个对应的控制器对象,然后从第5步继续执行; 3)如果不包含,在当前模块的模块属性(modules property)中查找此ID(1st ID)是否符合,如果符合,将创建一个新模块,以新模块为起点返回第2步继续执行; 4)如果不符合,将此ID(1st ID)视为控制器ID(controller ID),并创建一个控制器对象,继续下一步操作; 5)控制器在其动作映射表(action map)中查找当前ID(2nd ID),如果找到就创建一个动作,否则,控制器将尝试创建一个与当前动作ID(ation ID)相匹配的内联动作(inline action)。 以上步骤中,如果有错误发生,将抛出一个yii\web\NotFoundHttpException异常,描述路由解析过程的失败情况。

Default Route

如果一个请求被解析为空路由,将会调用默认路由(the so-called default route)。缺省的默认路由是site/index,将指向site控制器的index动作,你可以通过配置应用的defaultRoute属性来自定义默认路由:

[
    // ...
    'defaultRoute' => 'main/index',
];

与应用的默认路由相似,模块也有默认路由,例如,有一个user模块,解析到user模块的请求将由defaultRouter决定使用哪个控制器,控制器的默认路由是default。如果在defaultRoute中没有定义action,则控制器的defaultAction属性将被用于指定默认的动作,在本例中,全路由就是:user/default/index

catchAll Route

有时,你或许想在应用临时维护的过程中,将所有的请求指向同一个页面,有许多方法都可以实现,最简单的方法就是配置yii\web\Application::$catchAll 属性如下:

[
    // ...
    'catchAll' => ['site/offline'],
];

通过以上配置,site/offline动作将被用于处理所有的请求。 catchAll属性可以是一个数组,第一个元素定义了路由,其他元素(键-值对)定义绑定到动作的参数。 提示:开发环境中的调试面板(Debug panel)在此种模式下将不会工作。

3、Creating URLs

Yii2提供了yii\helpers\Url::to()方法用于创建URL,可以指定路由和查询参数,例如:

use yii\helpers\Url;

//错误的写法:
//echo Url::to('post/index');//生成的路径是:post/index,是个相对路径,不是绝对路径

//创建一个URL:/index.php?r=post%2Findex
echo Url::to(['post/index']);//生成的路径是:/post/index

//创建一个带参数的URL:/index.php?r=post%2Fview&id=100
echo Url::to(['post/view', 'id' => 100]);

//创建一个锚点URL:/index.php?r=post%2Fview&id=100#content
echo Url::to(['post/view', 'id' => 100, '#' => 'content']);

//创建一个绝对路径:http://www.example.com/index.php?r=post%2Findex
echo Url::to(['post/index'], true);

//使用https创建一个绝对路径:https://www.example.com/index.php?r=post%2Findex
echo Url::to(['post/index'], 'https');
测试结果:
/*
post/index
/post/index
/post/100
/post/100#content
http://localhost:8082/post/index
https://localhost:8082/post/index
*/

注意,在上例中,我们假定使用默认的URL格式,如果使用的是简洁URL(pretty URL),创建出来的URL会不同,主要依据的是使用的URL规则(URL rules) URL规则详细介绍: http://www.yiiframework.com/doc-2.0/yii-web-urlmanager.html#$rules-detail

传递给yii\helpers\Url::to()方法的路由参数是上下文敏感的,可以是一个相对路径,也可以是一个绝对路径,遵循的规则如下: 1、如果路由是一个空字符串,当前请路由将被使用; 2、如果路由中没有斜线,它将被认为是当前控制器的一个动作ID,并将添加上当前控制器的uniqueId; 3、如果路由左端不是以斜线开头,它将被认为是当前模块的相对路由,并将添加上当前模块的uniqueId。

源代码:
public function actionUrl(){
	echo Url::to();// /post/url
	echo "<br>";

	echo Url::to('');// /post/url
	echo "<br>";

	echo Url::to(['']);// /post/url
	echo "<br>";
}
测试结果:
http://localhost:8082/post/url
/*
/post/url
/post/url
*/
URL
//创建一个带参数的URL:/index.php?r=post%2Fview&id=100
echo Url::to(['post/view', 'id' => 100]);
依据urlManager配置的不同,生成的URL可能是以下格式(或更多)中的一种:
/index.php?r=post%2Fview&id=100
/index.php/post/100
/post/100 //本例中生成的格式
echo Url::to(['post2/viewbbc', 'id' => 100,'act'=>'this']);
/*
/post2/viewbbc/100?act=this
*/

从Yii 2.0.2开始,你可以定义一个别名形式的路由,在这种情况下,别名将首先被转换为一个实际路径,随后再依据上述规则转为一个绝对路径。

例如,假定当前模块是admin,当前控制器是post:

	use yii\helpers\Url;

	//当前的请求路径是:/index.php?r=admin%2Fpost%2Findex
	echo '<br>'.Url::to(['']);

	//仅有一个动作ID的相对路径是:/index.php?r=admin%2Fpost%2Findex
	echo '<br>index'.Url::to(['index']);

	//一个相对路由:/index.php?r=admin%2Fpost%2Findex
	echo '<br>post/index'.Url::to(['post/index']);

	//一个绝对路由:/index.php?r=post%2Findex
	echo '<br>/post/index'.Url::to(['/post/index']);

	// /index.php?r=post%2Findex     assume the alias "@posts" is defined as
	//使用别名@posts(/post/index)的路径:/index.php?r=post%2Findex
	Yii::setAlias('@posts', '/post/index');
	echo '<br>@posts:'.Url::to(['@posts']);
测试结果:
/*
/post/url
index/post/index
post/index/post/index
/post/index/post/index
@posts:/post/index
*/

yii\helpers\Url::to()方法是通过调用URL管理器的createUrl()和createAbsoluteUrl()方法实现的,在后续的章节里,我们将说明如何配置URL管理器(URL manager)实现自定义创建的URL的格式。 yii\helpers\Url::to()方法也支持未关联路径的URL,此时不用给它的首参数传递数组,而是一个字符串,例如:

	use yii\helpers\Url;

	//当前的请求路径URL: /index.php?r=admin%2Fpost%2Findex
	echo Url::to();

	//别名URL:http://example.com
	Yii::setAlias('@example', 'http://example.com/');
	echo Url::to('@example');

	//一个绝对路径:http://example.com/images/logo.gif
	echo Url::to('/images/logo.gif', true);
测试结果:
/*
/post/url
http://example.com
http://localhost:8082/images/logo.gif
*/

除了to()方法外,yii\helpers\Url类还提供了其他替代方法,例如:

	use yii\helpers\Url;

    //主页URL: /index.php?r=site%2Findex
	echo "home:".Url::home();
	echo "<br>";

	//基础URL,如果一个应用部署在一个网站应用的子目录下时此路径就很有用。
	echo "base:".Url::base();
	echo "<br>";

	//当前请求URL的canonical路径,详见:https://en.wikipedia.org/wiki/Canonical_link_element
	echo "canonical:".Url::canonical();
	echo "<br>";

	//记住当前请求的URL
	Url::remember();
	//获取上一页面记住的URL
	echo "previous:".Url::previous();
	echo "<br>";
测试结果:
/*
home:/
base:
canonical:http://localhost:8082/post/url
previous:/post/url
*/
4、Using Pretty URLs

使用简洁URL //pretty URL 要使用简洁URL,需要在应用配置中设置urlManager组件:

[
    'components' => [
        'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'enableStrictParsing' => false,
            'rules' => [
                // ...
            ],
        ],
    ],
]

enablePrettyUrl属性用于开关简洁URL格式,其他属性是可选的,以上配置是通用设置。 showScriptName,此属性决定是否在创建的URL中包含入口脚本文件,例如:此属性设置为false时,将使用/post/100,而不是/index.php/post/100 enableStrictParsing,此属性决定是否使用严格的请求解析。如果严格解析有效,进入的请求URL属性必须至少匹配一条规则可以处理成有效请求,或者执行一个yii\web\NotFoundHttpException异常。如果严格解析失效,当没有规则匹配请求的URL时,URL的部分路径信息将会处理成请求路由。 rules,此属性包含的是规则列表,定义了如何去解析和创建URL。这是你创建URL时主要设置的属性,它的格式将满足你特定的应用需求。

注意:如果要在生成的URL中隐藏入口脚本文件名,除了设置showScriptName为false外,你还需要配置Web server,当一个请求URL没有明确定义时能够正确识别由哪个PHP脚本去执行。如果你使用Apache Web服务器,你可以参考安装章节描述的推荐配置: http://www.yiiframework.com/doc-2.0/guide-start-installation.html#recommended-apache-configuration

URL规则(URL Rules)

URL规则是yii\web\UrlRule或其子类的实例,每个URL规则由一个匹配路径信息的模式(pattern)、一个路由(route)和一些查询参数(query parameter)组成。如果一个URL规则的模式与请求的URL相匹配,它就可以被解析为一个请求。如果一个URL规则的路由和参数名称符合所给定的,它就可以用于创建URL。

当简洁URL格式有效时,URL管理器使用规则属性中声明的URL规则去解析请求,并创建URL。特定情况下,要解析请求,URL管理器以定义的顺序检测规则,并查找第一条符合请求URL的规则。匹配的规则将被用于解析URL为一个带参数的路由。类似的,要创建一个URL,URL管理器查找符合给定路由和参数的第一条规则,并使用它去创建一个URL。

你可以配置yii\web\UrlManager::$rules 为一个数组,键名是模式,值是对应的路由,每个模式-路由对构成一个URL规则,例如:

[
	'posts'	=> 'post/index',
	'post/<id:\d+>'=>'post/view',
]

此配置定义了两个URL规则,第一个规则匹配URL"posts",并映射到路由"post/index",第二个规则匹配一个正则表达式"post/(\d+)",并映射到路由"post/view"和一个名为id的参数。

注意:规则中的模式(pattern)用于匹配URL中的路径部分,例如:"/index.php/post/100?source=ad"的路径(path)是post/100(首尾的斜线将被忽略),匹配的模式是"post/(\d+)"。

除了使用模式-路由对来定义URL规则之外,你还可以使用配置数组来定义,每个配置数组用于配置一个单独的URL规则对象,此种配置通常是发生在你需要在URL规则中还要配置其他属性的情况,例如:

[
	[
		'pattern'=>'posts'
		'route'=>'post/index',
		'suffix'=>'.json',
	]	
]

如果你没有定义规则配置的class,默认值是yii\web\UrlRule。

命名参数(Named Parameters)

一个URL规则可以与一些命名的查询参数相关联,这些参数的定义格式为:<ParamName:RegExp>,ParamName定义了参数名称,RegExp是可选的正则表达式,用于匹配参数值,如果RegExp没有定义,意味着参数值会是一个没有斜线的字符串。 注意:你可以为参数只定义正则表达式,模式的剩余部分被认为是文本。

当一个规则用于解析URL,它会与参数相关联,这些参数与URL中的相应部分相匹配,并随后被request应用组件放置到$_GET 中去。当规则用于创建一个URL时,它将从提供的参数中获取值,并将它们插入到参数声明的地方。 我们一起看个例程看看命名参数是如何工作的,假定我们已经声明了如下URL规则:

[
	'posts/<year:\d{4}>/<category>'	=>'post/index',
	'posts'=>'post/index',
	'post/<id:\d+>'=>'post/view',
]

当以上规则用于解析如下URL时:(根据左侧的模式创建路径(符合右侧的路由))

/index.php/posts,使用第2条规则,解析为路由post/index。
/index.php/posts/2014/php,使用第1条规则,解析为路由post/index,参数year的值是2014,参数category的值是php。
/index.php/post/100,使用第3条规则,解析为路由post/view,参数id的值是100。
/index.php/posts/php,当yii\web\UrlManager::$enableSrictParsing 为true时,将抛出一个yii\web\NotFoundHttpException异常;当yii\web\UrlManager::$enableSrictParsing 为false时(默认值),将返回路径部分posts/php作为路由。

当规则用于创建URL时:(解析的逆过程,根据右侧符合的路由,确定生成的路径(套用左侧的模式))

Url::to(['post/index']),使用第2条规则生成路径:/index.php/posts
//不是Url::to('post/index'),此句生成的路径:post/index
Url::to(['post/index','year'=>2014,'category'=>'php']),使用第1条规则生成路径:/index.php/posts/2014/php
Url::to(['post/view','id'=>100]),使用第3条规则生成路径:/index.php/post/100
Url::to(['post/view','id'=>100,'source'=>'ad']),使用第3条规则,生成路径:/index.php/post/100?source=ad,因为source参数在规则中未定义,所以它被追加到生成的URL末尾作为一个参数。
Url::to(['posts/index','category'=>'php']),不适用任何规则,生成路径:/index.php/posts/index?category=php。注意:因为不适用于任何规则,所以只是简单的将路由作为路径信息,参数作为查询字符串追加到生成的URL中。
Url::to(['post/index','category'=>'php']),使用第2条规则,生成路径:/index.php/posts?category=php,其他参数追加到URL尾。

//以上测试时的环境参数配置如下: D:\phpwork\advanced\common\config\main.php

源代码:
	'urlManager' => [
		'class' => 'yii\web\UrlManager',
		'showScriptName' => true,
		'enablePrettyUrl' => true,
		'rules'=>[
			'posts/<year:\d{4}>/<category>'	=>'post/index',
			'posts'=>'post/index',
			'post/<id:\d+>'=>'post/view',
		],
	]

//参数化路由(Parameterizing Routes) 你可以在URL规则的路由中添加参数名称,这样就允许一条URL规则适用于多条路由,例如,下例规则添加控制器(controller)和动作(action)参数到路由中:

[
	'<controller:(post|comment)>/<id:\d+>/<action:(create|update|delete)>'=>'<controller>/<action>',	
	'<controller:(post|comment)>/<id:\d+>'=>'<controller>/view',
	'<controller:(post|comment)>s'=>'<controller>/index',
]

解析URL /index.php/comment/100/creat,使用第1条规则,设置参数controller为comment,参数action为create,这样路由/就解析为comment/create。 类似的,为路由comment/index创建一个URL,第3条规则适用,将会创建一个URL:/index.php/comment

提示:使用参数路由,可以大大减少URL规则的数量,这样可以有效提升URL管理器的性能。

默认情况下,在一条规则中声明的所有参数都是必须的,如果一个请求URL中未包含一个特定参数,或者一个URL创建时未带特定参数,此规则将不适用。为了使一些参数成为可选项,你需要配置规则的默认属性,列在此属性中的参数如果没有被提供将使用一个预定值。 在下例规则声明中,page和tag参数均是可选的,如果没有被提供,它们将使用默认值1和空字符串。

[
	[
		'pattern'=>'posts/<page:\d+>/<tag>',
		'route'=>'post/index',
		'defaults'=>['page'=>1,'tag'=>''],
	]	
]

上例规则将可以解析和创建以下URL:

/index.php/posts,page是1,tag是''
/index.php/posts/2,page是2,tag是''
/index.php/posts/2/news,page是2,tag是'news'
/index.php/posts/news,page是1,tag是'news'

如果没有使用可选参数,你必须要创建4条规则才能实现以上效果。

//使用服务器名称的规则(Rules with Server Names) 可以在URL规则的模式中包含Web服务器名称,当你的应用与Web服务器名称不相同时,此项功能将非常有用,例如,下例规则将URL http::/ /admin.example.com/login 解析为路由admin/user/login,并将http::/ /www.example.com/login解析为site/login。

[
	'http://admin.example.com/login'=>'admin/user/login',	
	'http://www.example.com/login'=>'site/login',
]

你可以在服务器名称中使用参数替换动态信息,例如,下例规则将URL http:/ /en.example.com/posts 解析为路由post/index,并带有参数language=en。

[
	'http://<language:\w+>.example.com/posts'=>'post/index',
]

注意:含有服务器名称的规则不能被包含在入口脚本的子目录下。例如,如果当前应用位于http:/ /www.example.com/sandbox/blog,然后你应该使用模式http:/ /www.example.com/posts替换http:/ /www.example.com/sandbox/blog/posts,这样将允许你的应用无需修改代码即可部署在其他目录下。

//URL后缀(URL Suffixes) 你或许想要为不同的目的为URL添加后缀,例如,你想要为URL添加.html后缀,这样页面看起来更象是HTML静态页面;你或许想为URL添加.json后缀,以描述响应期望的内容类型,你可以通过配置yii\web\UrlManager::$suffix 属性实现此目的,应用配置代码如下:

[
    'components' => [
        'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'enableStrictParsing' => true,
            'suffix' => '.html',
            'rules' => [
                // ...
            ],
        ],
    ],
]

上述代码将允许URL管理器识别请求的URL,并创建带后缀.html的URL。 小贴士:你可以设置URL后缀为"/",这样所有的URL都以斜线结尾。 注意:当你配置了一个URL后缀,如果一个URL没有此后缀,它将被认为是不认识的URL,这是SEO的推荐做法。

你可以为不同的URL使用不同的后缀,在单独的URL规则中配置suffix属性即可。当一个URL规则有此属性设置,它将覆盖URL管理器中的后缀设置,例如:下例配置中包含一个自定义的URL规则,使用.json后缀替换了全局配置的.html。

[
'components' => [
	'urlManager' => [
		'enablePrettyUrl' => true,
		'showScriptName' => false,
		'enableStrictParsing' => true,
		'suffix' => '.html',
		'rules' => [
			// ...
			[
				'pattern' => 'posts',
				'route' => 'post/index',
				'suffix' => '.json',
			],
		],
	],
],
URL标准化(URL normalization)

从2.0.10版本起,URL管理器可以配置为使用UrlNormalizer处理带斜线和不带的URL。因为技术上http:/ /example.com/path和http:/ /example.com/path/是两个不同的URL,而它们提供相同的内容会降低SEO的效果。默认情况下,标准化会折叠斜线,根据后缀是否有尾斜线来决定添加或移除末尾斜线,使用永久重定向指向标准化的URL。标准化可以使用URL管理器进行全局配置,也可以为每一个规则进行单独配置,你可以设置UrlRule::$normalizer 为false,这样就可以为特定的URL规则禁用标准化。 下例展示了如何配置UrlNormalizer:

[
    'components' => [
        'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'enableStrictParsing' => true,
            'suffix' => '.html',
            'normalizer' => [
                'class' => 'yii\web\UrlNormalizer',
                'action' => UrlNormalizer::ACTION_REDIRECT_TEMPORARY, // 使用临时转向替代永久转向
            ],
            'rules' => [
                // ...
                [
                    'pattern' => 'posts',
                    'route' => 'post/index',
                    'suffix' => '/',
                    'normalizer' => false, //禁用标准化
                ],
                [
                    'pattern' => 'tags',
                    'route' => 'tag/index',
                    'normalizer' => [
                        'collapseSlashes' => false, //不折叠连续斜线
                    ],
                ],
            ],
        ],
    ],
]

注意:UrlManager::$nomalizer 默认是禁用的(disabled),如果要使用URL标准化,你需要明确配置它。

HTTP方法

实现RESTful API时,通常需要根据使用的HTTP方法将同一个URL解析为不同的路由,在规则的模式中添加支持的HTTP方法前缀即可轻松实现。如果一个规则支持多种HTTP方法,可以将各方法之间使用逗号分隔,例如:下例的规则支持不同的HTTP方法,但有相同的模式"post/<id:\d+>",一个请求PUT post/100将被解析为post/create,另一个请求GET post/100将被解析为post/view。

[
	'PUT,POST post/<id:\d+>'=>'post/create',
	'DELETE post/<id:\d+>'=>'post/delete',
	'post/<id:\d+>'=>'post/view',
]

注意:如果一个URL规则在其模式中包含HTTP方法,此规则则只能用于解析,当创建URL时此规则将被忽略。 小贴士:为了简化RESTful API路由,Yii提供了一个特殊的URL规则类yii\rest\UrlRule,它很有效并支持一些特性,如自动多元化控制器ID,更多细节请参考RESTful API开发的路由章节: http://www.yiiframework.com/doc-2.0/guide-rest-routing.html

自定义规则(Customizing Rules)

在此前的例子中,URL规则主要是使用模式-路由对的形式定义的,这是通常使用的简短形式,在特定情况下,你可能需要自定义URL规则,自定义一些属性,如yii\web\UrlRule::$suffix ,使用一个完整形式的数据定义此规则即可,下例就是从URL Suffixes部分摘取的:

[
    // ...other url rules...

    [
        'pattern' => 'posts',
        'route' => 'post/index',
        'suffix' => '.json',
    ],
]

信息:如果你没有为规则配置定义class选项,默认值将是yii\web\UrlRule。

动态添加规则(Adding Rules Dynamically)

URL规则可以被动态添加到URL管理器,此种情况在重新分发模块时经常发生,这些模块需要管理它们自己的URL规则。要使用动态添加的规则在规则处理的过程中生效,你需要在引导过程中添加规则。对于模块,意味着将在yii\base\BootstrapInterface中完成,并添加这些规则在bootstrap()方法,示例代码如下:

public function bootstrap($app){
	$app->getUrlManager()->addRules([
		//在此声明规则	
	],false);
}

注意:你也可以在yii\web\Application::bootstrap()中列出这些模块,这样就可以加入到引导过程了。

创建规则类(Creating Rule Classes)

尽管默认的yii\web\UrlRule类足够适用于项目的主要用途,但也有些情况下你必须创建自己的规则类。例如,在一个汽车销售网站,你或许会想要一种URL格式:/Manufacurer/Model,此处的Manufacturer和Model必须与数据库中存在的数据相匹配,默认的规则类在此处就无法使用,因为它是静态定义的模式。 我们可以创建如下的URL规则类来解决这个问题:

amespace app\components;

use yii\web\UrlRuleInterface;
use yii\base\Object;

class CarUrlRule extends Object implements UrlRuleInterface
{

    public function createUrl($manager, $route, $params)
    {
        if ($route === 'car/index') {
            if (isset($params['manufacturer'], $params['model'])) {
                return $params['manufacturer'] . '/' . $params['model'];
            } elseif (isset($params['manufacturer'])) {
                return $params['manufacturer'];
            }
        }
        return false;  // this rule does not apply
    }

    public function parseRequest($manager, $request)
    {
        $pathInfo = $request->getPathInfo();
        if (preg_match('%^(\w+)(/(\w+))?$%', $pathInfo, $matches)) {
            // check $matches[1] and $matches[3] to see
            // if they match a manufacturer and a model in the database
            // If so, set $params['manufacturer'] and/or $params['model']
            // and return ['car/index', $params]
        }
        return false;  // this rule does not apply
    }
}

然后在yii\web\UrlManager::$rules 配置中使用这个新的规则类:

[
	[
		'class'	=>'app\components\CarUrlRule',
		//配置其他属性
	]	
]
5、关于性能(Performance Consideration)

当开发一个复杂的Web应用时,优化URL规则以减少解析请求和创建URL的时间是非常重要的工作。 使用参数化路由,你可以减少URL规则的数量,并显著提升性能。 当解析或创建URL时,URL管理器按定义的顺序检测URL规则,所以,你可以考虑调整URL规则的顺序,将有效的、常用的规则放在其他规则的前面。 如果一些URL规则在模式或路由中使用了相同的前缀,你可以考虑使用yii\web\GroupUrlRule,这样它们可以在一个组中被URL管理器更有效的检测到,此种情况通常是你的应用由多个模块组成,每个有模块有自己的URL规则定义,并以模块ID作为公共前缀。

(全文完)

您需要登录后才可以回复。登录 | 立即注册