# TP5架构
[TOC]
* * * * *
## 一、架构总览
~~~
ThinkPHP5.0应用基于`MVC`:模型、视图、控制器 的方式组织。
MVC: 输入、处理、输出相分离
5.0的URL访问受路由决定,关闭或没有匹配到,则基于:
`http://serverName/index.php(或者其它应用入口文件)/模块/控制器/操作/参数/值…`
~~~
*****
## 二、基本概念
* 入口文件: `index.php` 、 `admin.php` 、 `think`...
* 应用: `think\App`
* 模块: `一个应用包括多个模块: 模块有自己的配置文件、公共文件、类库文件`、
`5.0支持单一模块架构设计(需配置)`
* 控制器(类):` 一个模块包含多个控制器(负责响应请求)`、`5.0可以通过路由跳过控制器,直接调用模型或其他类`
~~~
namespace app\index\controller;
class Index
{
public function index()
{
return 'hello,thinkphp!';
}
}
~~~
* 操作(方法): `一个控制器包含多个操作(方法)`
~~~
namespace app\index\controller;
class Index
{
public function index()
{
return 'index';
}
public function hello($name)
{
return 'Hello,'.$name;
}
}
~~~
* 模型: `完成实际的业务逻辑和数据封装,返回和格式无关的数据`、`惰性连接`、`支持多层设计:逻辑层、服务层、事件层`
* 视图:`视图根据不同的需求,来决定调用模板引擎进行内容解析后输出还是直接输出。`
* 驱动:`系统很多的组件都采用驱动式设计,从而可以更灵活的扩展。`
* 行为:`行为(Behavior)是在预先定义好的一个应用位置执行的一些操作。`
* 命名空间:
~~~
要执行行为,首先要在应用程序中进行行为侦听,例如:
// 在app_init位置侦听行为
\think\Hook::listen('app_init');
然后对某个位置进行行为绑定:
// 绑定行为到app_init位置
\think\Hook::add('app_init','\app\index\behavior\Test');
~~~
*****
## 三、生命周期
1. 入口文件
`public\index.php`:`定义常量等`
~~~
// 应用入口文件
// 定义项目路径
define('APP_PATH', __DIR__ . '/../application/');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';
~~~
2. 框架引导文件
`start.php`
~~~
1. 加载系统常量定义
2. 加载环境变量定义文件
3. 注册自动加载机制
4. 注册错误和异常处理机制
5. 加载惯例配置文件
6. 执行应用
~~~
3. 注册自动加载
`Loader::register()`
~~~
1. 注册系统的自动加载方法 \think\Loader::autoload
2. 注册系统命名空间定义
3. 加载类库映射文件(如果存在)
4. 如果存在Composer安装,则注册**Composer**自动加载
5. 注册extend扩展目录
~~~
4. 注册错误和异常机制
`Error:register()`
~~~
* 应用关闭方法: think\Error::appShutdown
* 错误处理方法: think\Error::appError
* 异常处理方法: think\Error::appException
~~~
5. 应用初始化
~~~
* 加载应用(公共)配置;
* 加载扩展配置文件(由extra_config_list定义);
* 加载应用状态配置;
* 加载别名定义;
* 加载行为定义;
* 加载公共(函数)文件;
* 注册应用命名空间;
* 加载扩展函数文件(由extra_file_list定义);
* 设置默认时区;
* 加载系统语言包;
~~~
6. URL访问检测
`PATH_INFO检测`、`URL后缀检测`
5.0的URL访问必须是`PATH_INFO`方式(或兼容方式):
`http://serverName/index.php/index/index/hello/val/value`
普通方式:
`http://serverName/index.php?s=/index/index/hello&val=value`
命令行访问:
`$php index.php index/index/hello/val/value...`
获取到正常的`$_SERVER['PATH_INFO']`参数后才能继续。
7. 路由检测
`url_route_on`参数开启,会首先检测URL路由:
5.0的地址支持:
~~~
* 路由到模块/控制器/操作;
* 路由到外部重定向地址;
* 路由到控制器方法;
* 路由到闭包函数;
* 路由到类的方法;
~~~
路由检测无效,则按照 *模块/控制器/操作* 分析识别
8. 分发请求
`应用请求的生命周期中最重要的环节`:`完成应用的业务逻辑及数据返回`
支持的分发请求机制:
~~~
* 模块/控制器/操作
* 控制器方法
* 外部重定向
* 闭包函数
* 类的方法:
* 静态方法:'blog/:id'=>'\org\util\Blog::read'
* 类的方法:'blog/:id'=>'\app\index\controller\Blog@read'
~~~
9. 响应输出
方法调用`return` 返回数据,系统会调用`Response::send`将应用返回的数据输出到页面,或客户端。,并自动转换成`default_return_type`参数配置的格式。
10. 应用结束
应用数据响应输出后,系统会进行日志保存写入操作。
*****
## 四、入口文件
**入口文件的任务:**
* [定义框架路径、项目路径]
* [定义系统常量]
* 载入框架入口文件
*****
**5.0默认入口文件**(可修改): `public\index.php`
~~~
// 定义应用目录
define('APP_PATH', __DIR__ . '/../application/');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';
~~~
(给`APP_PATH`定义绝对路径会提高系统的加载效率。)
*****
**框架引导文件**
`base.php` : 不会主动执行应用
`start.php` : 会主动执行
~~~
// 定义应用目录
define('APP_PATH', __DIR__ . '/../application/');
// 加载框架基础引导文件
require __DIR__ . '/../thinkphp/base.php';
// 添加额外的代码
// ...
// 执行应用
\think\App::run()->send();
~~~
*****
## 五、URL访问
**url设计:**
* 典型方式: http://serverName/index.php(或者其它应用入口文件)/模块/控制器/操作/[参数名/参数值...]
* 命令行模式:$ php.exe index.php(或者其它应用入口文件) 模块/控制器/操作/[参数名/参数值...]
命令行模式:$ php.exe index.php(或者其它应用入口文件) 模块/控制器/操作?参数名=参数值&...
* 兼容模式: http://serverName/index.php(或者其它应用入口文件)?s=/模块/控制器/操作/[参数名/参数值...]
**URL大小写**
`默认情况下,URL不区分大小写`。
如需要区分大小写,需改配置:
~~~
// 关闭URL中控制器和操作名的自动转换
'url_convert' => false,
~~~
`路由规则中定义的路由地址,区分大小写`
**隐藏入口文件**
配置过程:
~~~
1.httpd.conf配置文件中加载了mod_rewrite.so模块
2.AllowOverride None 将None改为 All
3.在应用入口文件同级目录添加.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>
~~~
nginx服务器配置见`URL重写`
*****
## 六、模块设计
**应用目录结构**
~~~
├─application 应用目录(可设置)
│ ├─common 公共模块目录(可选)
│ ├─common.php 公共函数文件
│ ├─route.php 路由配置文件
│ ├─database.php 数据库配置文件
│ ├─config.php 应用配置文件
│ ├─module1 模块1目录
│ │ ├─config.php 模块配置文件
│ │ ├─common.php 模块函数文件
│ │ ├─controller 控制器目录
│ │ ├─model 模型目录(可选)
│ │ ├─view 视图目录(可选)
│ │ └─ ... 更多类库目录
│ │
│ ├─module2 模块2目录
│ │ ├─config.php 模块配置文件
│ │ ├─common.php 模块函数文件
│ │ ├─controller 控制器目录
│ │ ├─model 模型目录(可选)
│ │ ├─view 视图目录(可选)
│ │ └─ ... 更多类库目录
~~~
`common`模块默认禁止直接访问,用于放置公共类库。
**模块类库**
模块命名空间:`app\模块名`
~~~
// index模块的Index控制器类
app\index\controller\Index
// index模块的User模型类
app\index\model\User
~~~
`app`可修改,配置中的: `'app_namespace' => 'application',`
**模块和控制器隐藏**
一个模块时的模块绑定,在入口文件中添加:
~~~
// 绑定当前访问到index模块
define('BIND_MODULE','index');
~~~
绑定后url可省略模块名:
`http://serverName/index.php/控制器/操作/[参数名/参数值...]`
如果只有一个模块,一个控制器,可在应用公共文件中绑定模块和控制器:
~~~
// 绑定当前访问到index模块的index控制器
define('BIND_MODULE','index/index');
~~~
只需url访问:
`http://serverName/index.php/操作/[参数名/参数值...]`
**单一模块**
应用只有一个模块,可简化应用结构:
1.改配置
~~~
// 关闭多模块设计
'app_multi_module' => false,
~~~
2.改目录结构
~~~
├─application 应用目录(可设置)
│ ├─controller 控制器目录
│ ├─model 模型目录
│ ├─view 视图目录
│ ├─ ... 更多类库目录
│ ├─common.php 函数文件
│ ├─route.php 路由配置文件
│ ├─database.php 数据库配置文件
│ └─config.php 配置文件
~~~
3.命名空间
~~~
app\controller\Index
app\model\User
~~~
4.url访问
`http://serverName/index.php(或者其它应用入口)/控制器/操作/[参数名/参数值...]`
****
*****
## 七、命名空间
*****
## 八、自动加载
*****
## 九、Traits引入
*****
## 十、API友好
*****