ThinkPHP6.0架构设计的一大亮点就是对多应用的更好支持,如果你有基于ThinkPHP的多个项目,不想每个项目都重复安装一堆的扩展包和依赖,可以使用多应用模式来开发和部署,支持给每个应用绑定域名或者单独的入口文件。
注意6.0版本不再使用模块的概念,每个应用下直接是控制器而没有模块,但可以支持多级控制器。如果你熟悉了5.1版本的模块,相当于6.0版本的应用概念。
多应用和之前版本的多模块设计最本质的区别在于,每个应用是完全独立的,而多模块只是一个应用下面的层次划分。多应用可以完成之前多模块的工作,同时也具有多模块不能完成的工作。
为了避免混淆,新版不再支持多模块的概念,如果你需要在一个应用下面划分更多的层次,可以使用多级控制器的方式。
但不要因此歧视单应用,事实上,单应用模式无所不能,只要你熟悉多级控制器的话,而且对URL有完全的掌控。
出于核心尽可能精简考虑,默认安装后的模式是单应用模式,如果你需要支持多应用模式,需要单独安装多应用支持扩展。
composer require topthink/think-multi-app
安装后你的目录结构就可以按照多应用模式的结构进行调整,下面是一个标准的多应用目录结构。
www WEB部署目录(或者子目录)
├─app 应用目录
│ ├─app_name 应用目录
│ │ ├─common.php 函数文件
│ │ ├─controller 控制器目录
│ │ ├─config 配置目录
│ │ ├─route 路由目录
│ │ ├─model 模型目录
│ │ ├─view 视图目录(优先)
│ │ └─ ... 更多类库目录
│ │
│ ├─common.php 全局公共函数文件
│ ├─event.php 全局事件定义文件
│ ├─ExceptionHandle.php应用异常处理类
│ ├─middleware.php 全局中间件定义文件
│ ├─provider.php 全局容器绑定定义文件
│ └─Request.php 应用请求对象类
│
├─config 全局配置目录
│ ├─app.php 应用配置
│ ├─cache.php 缓存配置
│ ├─console.php 控制台配置
│ ├─cookie.php Cookie配置
│ ├─database.php 数据库配置
│ ├─filesystem.php 文件磁盘配置
│ ├─lang.php 多语言配置
│ ├─log.php 日志配置
│ ├─middleware.php 中间件配置
│ ├─route.php URL和路由配置
│ ├─session.php Session配置
│ ├─trace.php Trace配置
│ └─view.php 视图配置
│
├─view 视图目录
│ ├─app_name 应用视图目录
│ └─ ...
│
├─public WEB目录(对外访问目录)
│ ├─index.php 入口文件
│ ├─router.php 快速测试文件
│ └─.htaccess 用于apache的重写
│
├─extend 扩展类库目录
├─runtime 应用的运行时目录(可写,可定制)
├─vendor 第三方类库目录(Composer依赖库)
├─build.php 自动生成定义文件(参考)
├─composer.json composer 定义文件
├─LICENSE.txt 授权说明文件
├─README.md README 文件
├─think 命令行入口文件
注意,多应用模式下,每个应用的路由定义是独立的。
多应用模式在设计的时候已经考虑到了每个应用的完全独立(甚至支持composer方式扩展应用),包括视图文件、路由定义以及配置文件都直接纳入应用目录下,只需要在应用目录下创建对应的view、route和config目录即可。
快速创建应用
你可以通过指令快速创建一个应用,例如创建一个demo应用。
php think build demo
创建成功后,我们可以通过访问
http://tp.com/demo
访问应用。
应用名必须使用小写,否则在Linux环境下可能会出错。
多入口文件
允许为每个应用创建单独的入口文件访问,例如创建一个admin.php入口文件来访问admin应用,你只需要在入口文件中添加下面的代码。
// [ 应用入口文件 ]
namespace think;
require __DIR__ . '/../vendor/autoload.php';
// 执行HTTP应用并响应
$http = (new App())->http;
$response = $http->run();
$response->send();
$http->end($response);
原则上,多应用模式下,每个应用都可以有一个独立的入口文件,例如index.php 作为前台应用入口,admin.php 作为后台应用入口。入口文件的代码基本上完全一样,系统会自动使用入口文件名作为应用名。
一个特例是,如果你要把index.php入口绑定index应用,你必须显式指定应用名,否则会自动作为自动多应用入口文件。
// [ 应用入口文件 ]
namespace think;
require __DIR__ . '/../vendor/autoload.php';
// 执行HTTP应用并响应
$http = (new App())->http;
$response = $http->name('index')->run();
$response->send();
$http->end($response);
多入口的应用访问
规则是
http://tp.com/index.php/controllerName/actionName
http://tp.com/admin.php/controllerName/actionName
一般情况下,我们会通过URL重写把index.php入口隐藏,访问index应用通常变成
http://tp.com/controllerName/actionName
使用多个入口文件的一个好处是,你可以针对某个应用单独开启调试模式,或者在入口文件中增加额外的设置。
// [ 应用入口文件 ]
namespace think;
require __DIR__ . '/../vendor/autoload.php';
// 执行HTTP应用并响应 开启调试模式
$http = (new App())->debug(true)->http;
$response = $http->name('index')->run();
$response->send();
$http->end($response);
自动多应用部署
如果你有超过两个应用,那么强烈建议你使用自动多应用部署,优势是使用同一个入口文件访问不同的应用,和使用多个入口文件没有本质的区别,而且URL更加优雅。
如果你的入口文件是index.php,则会默认使用自动多应用模式,应用访问地址变成(index.php入口文件已经通过URL重写隐藏)
// 访问index应用
http://tp.com/index/controllerName/actionName
// 访问admin应用
http://tp.com/admin/controllerName/actionName
自动多应用模式下,引入了路由网关的概念,你可以对URL的应用访问设置映射。
在config\app.php配置文件中设置
'app_map' => [
'home' => 'index',
'think' => 'admin',
],
这样,当我们访问
http://tp.com/home/ 其实是访问index应用
http://tp.com/think/ 其实是访问admin应用
你可以给index应用和admin应用定义路由,但不能省略URL里面的应用名。应用名后面的才是路由定义生效的URL。要希望省略应用名的最好办法就是给应用绑定域名。
如果希望把home和think之外的URL访问都映射到index应用,可以添加泛应用解析,但必须显式定义所有的应用。
'app_map' => [
'home' => 'index',
'think' => 'admin',
'*' => 'index',
],
当定义泛应用映射的时候,必须首先定义所有的应用。
如果不希望通过URL访问某个特殊的应用(例如common应用可能只是用于放置一些公共类库之类的),可以在app.php配置文件中设置禁止访问的应用列表
// 设置禁止URL访问的应用列表
'deny_app_list' => ['common'],
自动多应用模式由于一个入口要访问不同的应用,所以URL里面的应用名不能省略,如果不希望在URL里面显示应用名,你可以给每个应用绑定一个域名(或者子域名)
'domain_bind' => [
'admin.tp.com' => 'admin',
'blog' => 'blog',
'user' => 'user',
'*' => 'index',
],
域名绑定设置支持完整域名和子域名的方式(当然也支持IP地址),并且支持泛域名绑定。
现在,你可以访问
http://admin.tp.com //访问admin应用
http://blog.tp.com //访问blog应用
http://user.tp.com //访问user应用
http://a.tp.com //访问index应用
你也可以把多个域名绑定到同一个应用上(类似于单应用模式),然后在该应用的路由里面定义不同的域名路由规则。总之,进入某个应用后,URL的权限就都交给路由来控制了。
多应用智能识别
前面说过,给不同的应用绑定不同的域名或者入口是简化URL地址最有效的办法,如果没有绑定入口或者域名的情况下,URL里面的应用名其实是会自动识别的,假设我们访问一个不存在的应用,例如访问:
http://tp.com/think
假设并不存在think应用,这个时候系统会自动切换到单应用模式,如果有定义全局的路由,也会进行路由匹配检查,例如我们在route/route.php全局路由中注册了think路由规则:
Route::get('think', function () {
return 'hello,ThinkPHP!';
});
访问上面的URL就会输出
hello,ThinkPHP!
实际上是首先定位think应用是否存在,因为这里think应用不存在,所以会去匹配全局路由,如果没有匹配到全局路由的话,那么会把think当成单应用的控制器。
如果你希望think应用不存在的时候,直接访问默认应用的路由,可以在app.php中配置
// 开启应用快速访问
'app_express' => true,
// 默认应用
'default_app' => 'home',
这个时候就会访问home应用下的think路由规则而不是全局路由规则。
其它注意事项
多应用模式下,无法监听应用的AppInit和HttpRun事件,因为在多应用解析之前这两个事件已经完成分发了。如果有类似需求,应该改成应用中间件执行或者在全局事件定义文件中添加监听。
发表评论