工学1号馆

home

« | 返回首页 | »

ThinkPHP5.0快速入门--URL和路由

By Wu Yudong on November 09, 2017

因为每次域名很长很麻烦,所以先配置一下项目域名,将其改为tp5.com

首先修改apache的http.conf文件,加入下面的代码:

<VirtualHost *:80>
DocumentRoot "D:\workspace\tp5\public"
ServerName www.tp5.com
</VirtualHost>

然后修改C:\Windows\System32\drivers\etc文件,加入:127.0.0.1  tp5.com

这样访问tp5.com就取代访问http://localhost/tp5/public/


URL访问

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

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

如果我们直接访问入口文件的话,由于URL中没有模块、 控制器和操作,因此系统会访问默认模块(index)下面的默认控制器(Index)的默认操作(index),因此下面的访问是等效的:

http://tp5.com/index.php

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

class Index extends Controller
{
    public function hello($name='World'){
    	return 'Hello,'.$name.'!';
    }
}

如果要访问控制器的hello方法,则需要使用完整的URL地址
http://tp5.com/index.php/index/index/hello/name/thinkphp

由于 name 参数为可选参数,因此也可以使用http://tp5.com/index.php/index/index/hello直接使用默认的参数

默认情况下,URL地址中的控制器和操作名是不区分大小写的,因此下面的访问其实是等效的:

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

http://tp5.com/index.php/index/INDEX/INDEX

如果你习惯使用驼峰命名的控制器名称,比如定义一个 HelloWorld控制器(
application/index/controller/HelloWorld.php ):

<?php
namespace app\index\controller;

class HelloWorld{
	public function index($name='World'){
		return 'Hello,'.$name.'!';
	}
}

如果你访问:http://tp5.com/index.php/HelloWorld/index/hello

则提示“控制器不存在:Helloworld”错误

正确的URL访问地址(该地址可以使用url方法生成)应该是:

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

如果希望严格区分大小写访问(或者要支持驼峰法进行控制器访问),可以在应用配置文件中设置:

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

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

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

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

URL

通过操作方法的参数绑定功能,可以实现自动获取URL的参数,仍然以上面的控制器为例,控制器代码如下:

class Index extends Controller
{
    public function index()
    {
    	return  'index';
    }

    public function hello($name='World'){
    	return 'Hello,'.$name.'!';
    }
}

如果访问:http://tp5.com/index.php/index/index/hello 就是访问 app\index\controller\Index 控制器类的 hello 方法,因为没有传入任何参数, name 参数就使用默认值 World 。 如果传入name参数,则使用:

http://tp5.com/index.php/index/index/hello/name/wuyudong

现在给hello方法增加第二个参数:

class Index extends Controller
{
    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 方法会自动获取URL地址中的同名参数值作为方法的参数值,而且这个参数的传入顺序不受URL参数顺序的影响

隐藏index.php

我使用的是tp5.0.10版本,所以直接去掉index.php也能正常访问

定义路由

URL地址里面的 index 模块怎么才能省略呢,默认的URL地址显得有点长,下面就来说说如何通过路由简化URL访问。我们在路由定义文件( application/route.php )里面添加一些路由规则,如下:

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地址将会失效,变成非法请求。

进一步修改路由规则:

return [
    
    // 添加路由规则 路由到 index控制器的hello操作方法
    'hello/[:name]' => 'index/hello',
];

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

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

这样就可以指定文件进行路由配置了

完成的效果和使用配置方式定义是一样的。无论是配置方式还是通过Route类的方法定义路由,都统一放到路由配置文件 application/route.php文件中,具体原因后面会揭晓。

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

完整匹配

前面定义的路由是只要以hello开头就能进行匹配,意思就是http://tp5.com/hello/thinkphp/wu/www/ww/ww...,均能正确显示,如果需要完整匹配,可以使用下面的定义:

use think\Route;
Route::rule('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分隔符

如果需要改变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 // 有效

变量规则

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

<?php

namespace app\index\controller;

class Blog {
	public function get($id) {
		return '查看id=' . $id . '的内容';
	}
	public function read($name) {
		return '查看name=' . $name . '的内容';
	}
	public function archive($year, $month) {
		return '查看' . $year . '/' . $month . '的归档内容';
	}
}

添加如下路由规则:

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访问的情况:

// 访问id5的内容
http://tp5.com/blog/5
//
访问namethinkphp的内容
http://tp5.com/blog/thinkphp
//
访问20155月的归档内容
http://tp5.com/blog/2015/05

路由分组

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

//路由分组
'[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+']]
],

路由分组一定程度上可以提高路由检测的效率。

 

如果文章对您有帮助,欢迎点击下方按钮打赏作者

Comments

No comments yet.
To verify that you are human, please fill in "七"(required)