# 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友好
*****