相思资源网 Design By www.200059.com

前面的话

本文将详细介绍thinkphp5URL和路由

URL访问

ThinkPHP采用单一入口模式访问应用,对应用的所有请求都定向到应用的入口文件,系统会从URL参数中解析当前请求的模块、控制器和操作,下面是一个标准的URL访问格式:

http://domainName/index.php/模块/控制器/操作

其中index.php就称之为应用的入口文件(注意入口文件可以被隐藏,后面会提到)

模块在ThinkPHP中的概念其实就是应用目录下面的子目录,而官方的规范是目录名小写,因此模块全部采用小写命名,无论URL是否开启大小写转换,模块名都会强制小写

应用的index模块的Index控制器定义如下:

<"htmlcode">
<"htmlcode">
// 关闭URL自动转换(支持驼峰访问控制器)
'url_convert' => false,

关闭URL自动转换之后,必须使用下面的URL地址访问(控制器名称必须严格使用控制器类的名称,不包含控制器后缀):

http://tp5.com/index.php/index/Index/index
http://tp5.com/index.php/index/HelloWorld/index

如果服务器环境不支持pathinfo方式的URL访问,可以使用兼容方式,例如:

http://tp5.com/index.php"htmlcode">

<"htmlcode">
public function hello($name = 'World', $city = '')
  {
    return 'Hello,' . $name . '! You come from ' . $city . '.';
  }

访问地址为http://tp5.com/index.php/index/index/hello/name/thinkphp/city/shanghai

页面输出结果为:

Hello,thinkphp! You come from shanghai.

可以看到,hello方法会自动获取URL地址中的同名参数值作为方法的参数值,而且这个参数的传入顺序不受URL参数顺序的影响,例如下面的URL地址输出的结果和上面是一样的:

http://tp5.com/index.php/index/index/hello/city/shanghai/name/thinkphp

或者使用http://tp5.com/index.php/index/index/hello"htmlcode">

// 按照参数顺序获取
'url_param_type' => 1,

现在,URL的参数传值方式就变成了严格按照操作方法的变量定义顺序来传值了,也就是说我们必须使用下面的URL地址访问才能正确传入name和city参数到hello方法:http://tp5.com/index.php/index/index/hello/thinkphp/shanghai

页面输出结果为:

Hello,thinkphp! You come from shanghai.

如果改变参数顺序为http://tp5.com/index.php/index/index/hello/shanghai/thinkphp

页面输出结果为:

Hello,shanghai! You come from thinkphp.

显然不是我们预期的结果。

同样,我们试图通过http://tp5.com/index.php/index/index/hello/name/thinkphp/city/shanghai

访问也不会得到正确的结果

[注意]按顺序绑定参数的话,操作方法的参数只能使用URL pathinfo变量,而不能使用get或者post变量

隐藏入口

可以去掉URL地址里面的入口文件index.php,但是需要额外配置WEB服务器的重写规则。

以Apache为例,需要在入口文件的同级添加.htaccess文件(官方默认自带了该文件),内容如下

<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>

如果用的phpstudy,规则如下:

<IfModule mod_rewrite.c> 
Options +FollowSymlinks -Multiviews 
RewriteEngine on 
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteRule ^(.*)$ index.php [L,E=PATH_INFO:$1] 
</IfModule>

接下来就可以使用下面的URL地址访问了

http://tp5.com/index/index/index
http://tp5.com/index/index/hello

如果使用的apache版本使用上面的方式无法正常隐藏index.php,可以尝试使用下面的方式配置.htaccess文件:

<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php"htmlcode">
location / { // …..省略部分代码
  if (!-e $request_filename) {
    rewrite ^(.*)$ /index.php"htmlcode">
return [
  // 添加路由规则 路由到 index控制器的hello操作方法
  'hello/:name' => 'index/index/hello',
];

该路由规则表示所有hello开头的并且带参数的访问都会路由到index控制器的hello操作方法。

路由之前的URL访问地址为:http://tp5.com/index/index/hello/name/thinkphp

定义路由后就只能访问下面的URL地址http://tp5.com/hello/thinkphp

[注意]定义路由规则后,原来的URL地址将会失效,变成非法请求。

但这里有一个小问题,如果我们只是访问http://tp5.com/hello

将发生错误

事实上这是由于路由没有正确匹配到,我们修改路由规则如下:

return [
  // 路由参数name为可选
  'hello/[:name]' => 'index/hello',
];

使用[]把路由规则中的变量包起来,就表示该变量为可选,接下来就可以正常访问了http://tp5.com/hello

当name参数没有传入值的时候,hello方法的name参数有默认值World,所以输出的内容为 Hello,World!

除了路由配置文件中定义之外,还可以采用动态定义路由规则的方式定义,例如在路由配置文件(application/route.php)的开头直接添加下面的方法:

use think\Route;
Route::rule('hello/:name', 'index/hello');

完成的效果和使用配置方式定义是一样的。

无论是配置方式还是通过Route类的方法定义路由,都统一放到路由配置文件application/route.php文件中

[注意]路由配置不支持在模块配置文件中设置

【完整匹配】

前面定义的路由是只要以hello开头就能进行匹配,如果需要完整匹配,可以使用下面的定义:

return [
  // 路由参数name为可选
  'hello/[:name]$' => 'index/hello',
];

当路由规则以$结尾的时候就表示当前路由规则需要完整匹配。

当我们访问下面的URL地址的时候:

http://tp5.com/hello // 正确匹配
http://tp5.com/hello/thinkphp // 正确匹配
http://tp5.com/hello/thinkphp/val/value // 不会匹配

【闭包定义】

还支持通过定义闭包为某些特殊的场景定义路由规则,例如:

return [
  // 定义闭包
  'hello/[:name]' => function ($name) {
    return 'Hello,' . $name . '!';
  },
];

或者

use think\Route;
Route::rule('hello/:name', function ($name) {
  return 'Hello,' . $name . '!';
});

[注意]闭包函数的参数就是路由规则中定义的变量

因此,当访问下面的URL地址:http://tp5.com/hello/thinkphp

会输出

Hello,thinkphp!

【设置URL分隔符】

如果需要改变URL地址中的pathinfo参数分隔符,只需要在应用配置文件(application/config.php)中设置:

// 设置pathinfo分隔符
'pathinfo_depr'     => '-',

路由规则定义无需做任何改变,我们就可以访问下面的地址:http://tp5.com/hello-thinkphp

【路由参数】

还可以约束路由规则的请求类型或者URL后缀之类的条件,例如:

return [
  // 定义路由的请求类型和后缀
  'hello/[:name]' => ['index/hello', ['method' => 'get', 'ext' => 'html']],
];

上面定义的路由规则限制了必须是get请求,而且后缀必须是html的,所以下面的访问地址:

http://tp5.com/hello // 无效
http://tp5.com/hello.html // 有效
http://tp5.com/hello/thinkphp // 无效
http://tp5.com/hello/thinkphp.html // 有效

【变量规则】

接下来,尝试一些复杂的路由规则定义满足不同的路由变量。在此之前,首先增加一个控制器类如下:

<"htmlcode">
return [
  'blog/:year/:month' => ['blog/archive', ['method' => 'get'], ['year' => '\d{4}', 'month' => '\d{2}']],
  'blog/:id'     => ['blog/get', ['method' => 'get'], ['id' => '\d+']],
  'blog/:name'    => ['blog/read', ['method' => 'get'], ['name' => '\w+']],
];

在上面的路由规则中,我们对变量进行的规则约束,变量规则使用正则表达式进行定义。

我们看下几种URL访问的情况

// 访问id为5的内容
http://tp5.com/blog/5
// 访问name为thinkphp的内容
http://tp5.com/blog/thinkphp
// 访问2015年5月的归档内容
http://tp5.com/blog/2015/05

 【路由分组】

上面的三个路由规则由于都是blog打头,所以我们可以做如下的简化:

return [
  '[blog]' => [
    ':year/:month' => ['blog/archive', ['method' => 'get'], ['year' => '\d{4}', 'month' => '\d{2}']],  
    ':id'     => ['blog/get', ['method' => 'get'], ['id' => '\d+']],
    ':name'    => ['blog/read', ['method' => 'get'], ['name' => '\w+']],
  ],
];

对于这种定义方式,我们称之为路由分组,路由分组一定程度上可以提高路由检测的效率

【复杂路由】

有时候,还需要对URL做一些特殊的定制,例如如果要同时支持下面的访问地址

http://tp5.com/blog/thinkphp
http://tp5.com/blog-2015-05

我们只要稍微改变路由定义规则即可:

return [
  'blog/:id'      => ['blog/get', ['method' => 'get'], ['id' => '\d+']],
  'blog/:name'     => ['blog/read', ['method' => 'get'], ['name' => '\w+']],
  'blog-<year>-<month>' => ['blog/archive', ['method' => 'get'], ['year' => '\d{4}', 'month' => '\d{2}']],
];

对 blog-<year>-<month> 这样的非正常规范,我们需要使用<变量名>这样的变量定义方式,而不是 :变量名方式。

简单起见,我们还可以把变量规则统一定义,例如:

return [
  // 全局变量规则定义
  '__pattern__'     => [
    'name' => '\w+',
    'id'  => '\d+',
    'year' => '\d{4}',
    'month' => '\d{2}',
  ],
  // 路由规则定义
  'blog/:id'      => 'blog/get',
  'blog/:name'     => 'blog/read',
  'blog-<year>-<month>' => 'blog/archive',
];

在__pattern__中定义的变量规则我们称之为全局变量规则,在路由规则里面定义的变量规则我们称之为局部变量规则,如果一个变量同时定义了全局规则和局部规则的话,当前的局部规则会覆盖全局规则的,例如:

return [
  // 全局变量规则
  '__pattern__'     => [
    'name' => '\w+',
    'id'  => '\d+',
    'year' => '\d{4}',
    'month' => '\d{2}',
  ],

  'blog/:id'      => 'blog/get',
  // 定义了局部变量规则
  'blog/:name'     => ['blog/read', ['method' => 'get'], ['name' => '\w{5,}']],
  'blog-<year>-<month>' => 'blog/archive',
];

URL生成

定义路由规则之后,可以通过Url类来方便的生成实际的URL地址(路由地址),针对上面的路由规则,我们可以用下面的方式生成URL地址。

// 输出 blog/thinkphp
Url::build('blog/read', 'name=thinkphp');
Url::build('blog/read', ['name' => 'thinkphp']);
// 输出 blog/5
Url::build('blog/get', 'id=5');
Url::build('blog/get', ['id' => 5]);
// 输出 blog/2015/05
Url::build('blog/archive', 'year=2015&month=05');
Url::build('blog/archive', ['year' => '2015', 'month' => '05']);

[注意]build方法的第一个参数使用路由定义中的完整路由地址

还可以使用系统提供的助手函数url来简化

url('blog/read', 'name=thinkphp');
// 等效于
Url::build('blog/read', 'name=thinkphp');

通常在模板文件中输出的话,可以使用助手函数,例如:

{:url('blog/read', 'name=thinkphp')}

如果我们的路由规则发生调整,生成的URL地址会自动变化

如果你配置了url_html_suffix参数的话,生成的URL地址会带上后缀,例如:

'url_html_suffix'  => 'html',

那么生成的URL地址 类似

blog/thinkphp.html 
blog/2015/05.html

如果你的URL地址全部采用路由方式定义,也可以直接使用路由规则来定义URL生成,例如:

url('/blog/thinkphp');
Url::build('/blog/8');
Url::build('/blog/archive/2015/05');

生成方法的第一个参数一定要和路由定义的路由地址保持一致,如果你的路由地址比较特殊,例如使用闭包定义的话,则需要手动给路由指定标识,例如: 

// 添加hello路由标识
Route::rule(['hello','hello/:name'], function($name){
  return 'Hello,'.$name;
});
// 根据路由标识快速生成URL
Url::build('hello', 'name=thinkphp');
// 或者使用
Url::build('hello', ['name' => 'thinkphp']);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

标签:
thinkphp5,URL和路由,thinkphp5,路由,thinkphp5,URL

相思资源网 Design By www.200059.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
相思资源网 Design By www.200059.com

评论“thinkphp5 URL和路由的功能详解与实例”

暂无thinkphp5 URL和路由的功能详解与实例的评论...

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。