### 2018 年 12 月 15 日 發布
>[info] ThinkPHP作為堅持十多年的老牌框架,始終秉承著「大道至簡,開發由我」的開發理念,逐漸形成了一套自己的開發規范,在歷史版本的迭代過程中,也曾多次完善并趨于規范。
本文就來總結下目前最新版本的開發規范,但可能由于篇幅原因無法涵蓋所有的PHP開發規范,而僅僅是框架層面的使用規范。建議閱讀官方開發者周刊第3期發布過的「[PHP版的代碼整潔之道 中文翻譯](https://github.com/php-cpm/clean-code-php)」以及「[PHP之道](http://www.hmoore.net/thinkphp/php-the-right-way/3126)」作為本文很好的代碼規范補充,相信一定會獲益良多。
## 選擇合適的版本
### 框架版本
ThinkPHP目前主要存在三個版本,很多人容易困惑到底應該選擇哪個版本開發。如果你是新接觸ThinkPHP,那么毫無疑問`5.1`版本是當然之選,時代在進步,技術永遠用新不用舊,何況沒有任何的包袱。
如果你之前接觸過`3.2`或者`5.0`版本,有線上運營產品想升級到最新的版本,那我會建議你謹慎考慮,因為升級并非無縫,而且單純的升級代碼沒法真正使用和發揮新版的特性,如果開發思想不升級的話。最合適的選擇應該是關注官方的安全更新,進行小版本升級。
如果你的產品已經被用戶廣泛使用,出于品牌戰略發展考慮,那我建議你在保留老版本運營的前提下,盡快把基于`5.1 LTS`版本重構納入下一代產品計劃,也許對一些新客戶有更好的說服力。
>[info] 任何時候,當你開始規劃商業產品的開發工作,出于安全性和穩定性考慮,應該首先選擇最新的`LTS`版本。
下面給出官方主要版本的生命周期,供版本選擇參考:
|ThinkPHP版本|發布時間|BUG修復|安全更新|
|---|---|---|---|
|3.2(PHP5.3+)|2013年12月18日|結束服務|結束服務|
|5.0(PHP5.4+)|2016年9月15日|2019年1月1日|2020年1月1日|
|5.1 LTS(PHP5.6+)|2018年1月1日|2020年1月1日|2021年1月1日|
最后,如果你僅僅是因為興趣而非工作,并且樂于接受新技術和一定的探索精神,愿意給官方進行測試反饋,那么`5.2`版本(目前還是`Beta`版本)不失為一個不錯的選擇。歡迎有更多的朋友參與ThinkPHP下一代產品的建設和貢獻中。
### PHP版本
如果是新的項目,目前應該盡量選擇PHP`7.1+`作為你的PHP版本(ThinkPHP`5.1`版本可以很好的支持`7.1+`),可以擁有更好的性能,不再建議使用低于`7.0`的版本,官方已經不再提供技術支持服務,意味著不會有任何的安全更新。
>[danger] 有些PHP擴展可能不支持PHP的高版本,這個時候你要做出選擇,使用低版本還是尋求更好的擴展解決方案。
## 保持測試環境和部署環境的一致性
在開發過程中,應該盡量保持你的測試環境和正式部署環境的一致性,包括運行環境和版本,無論在本地測試環境還是部署環境,都應當統一使用域名方式訪問,本地可以使用測試域名,例如你的正式部署域名為`thinkphp.cn`,那么本地測試環境可以使用`thinkphp`或者`thinkphp.test`作為測試域名,避免使用`localhost`或者`127.0.0.1`這種測試地址。對于有多個域名的部署應用,本地也要盡量模擬多個域名。
## 配置部署忽略清單
項目根目錄下面有一個`.gitignore`文件,用于定義提交版本庫的時候哪些文件或者目錄需要忽略,設置忽略的文件不會被同步到遠程服務器,只是用于本地開發。
該文件默認內容如下,你可以根據項目的目錄和規范進行調整。
```
/.idea
/.vscode
/vendor
*.log
thinkphp
.env
```
項目使用的核心框架以及`composer`安裝的擴展,不應當被同步到版本庫中,只需要同步`composer.json`以及`composer.lock`文件。然后在服務器端進行`composer`更新。
## 使用統一的IDE以及代碼規范配置或者插件
項目團隊應當盡量使用統一的IDE作為開發工具,并規范一致的代碼規范配置項,如果使用的第三方代碼規范及自動完成插件。如果團隊成員較多而無法完全統一,最低限度,項目代碼風格必須遵循`PSR-1`和`PSR-2`規范。
## 基本命名規范
ThinkPHP遵循`PSR-2`命名規范以及`PSR-4`自動加載規范,并注意如下規范:
### 類和文件命名
* 類(包括接口、Trait)文件名和類名保持一致,并且使用首字母大寫的駝峰命名;
* 函數文件、配置文件、路由定義文件等文件名使用小寫規范;
* 無論類還是普通文件都使用`.php`后綴;
* 目錄名統一使用小寫規范,并且使用單數規范;
* 模板文件使用小寫規范;
### 配置和變量命名
* 配置參數名統一使用小寫規范;
* 常量定義統一使用大寫規范;
* 環境變量定義統一使用大寫規范;
### 函數和類、屬性命名
* 函數的命名使用小寫字母和下劃線(小寫字母開頭)的方式,例如 `get_client_ip`;
* 方法的命名使用駝峰法(首字母小寫),例如 `getUserName`;
* 屬性的命名使用駝峰法(首字母小寫),例如 `tableName`、`instance`;
* 特例:以雙下劃線`__`打頭的函數或方法作為魔術方法,例如` __call` 和 `__callStatic`;
### 數據表命名
數據表和字段采用小寫加下劃線方式命名,例如 `think_user `表和 `user_name`字段,禁止使用駝峰、中文或者拼音作為數據表及字段命名。
## 配置規范化
線上環境和本地測試環境應該使用一致的配置文件,差異化的配置使用環境變量方式處理。本地環境可以通過定義`.env`文件(注意添加到忽略文件列表)來模擬環境變量。
在你需要差異化配置的參數中使用`env`函數定義,例如:
```
'db_host' => env('db_host', '127.0.0.1'),
```
然后在環境變量中或者本地`.env`中定義
```
DB_HOST = 192.168.0.12
```
盡量不要在配置文件以外使用`env`函數獲取配置參數。統一使用`config`函數獲取配置參數。
除了定義配置文件之外,避免使用動態配置功能,保持僅讀取配置參數的良好習慣。
如果需要提高配置文件的性能,可以考慮使用`Yaconf`擴展。ThinkPHP核心已經支持`Yaconf`配置定義,參考:[在ThinkPHP使用Yaconf](https://blog.thinkphp.cn/783762)。
## 是否應當使用助手函數
助手函數的初衷是為了簡化代碼和更方便記憶,但如果不是很清楚助手函數的內部實現原理,很容易導致濫用,例如`db`助手函數就是一個非常典型的例子。
`db`助手函數設計的時候,因為`Db`類是一個靜態單例對象,而且`5.1`版本的數據查詢設計為每次查詢后不會清空當前對象的查詢條件,為了避免下面的代碼查詢條件產生混淆,`db`函數被設計成每次重新連接。
```
db('user')->where('status', 1)->select();
db('user')->where('name', 'thinkphp')->select();
```
因此下面的代碼中,循環中的每次查詢都會重新連接一次數據庫,從而造成超過數據庫的最大連接數錯誤。
```
foreach($users as $name) {
db('user')->where('name', $name)->update(['status' => 1]);
}
```
上面的代碼建議使用`Db`類直接操作
```
foreach($users as $name) {
Db::name('user')->where('name', $name)->update(['status' => 1]);
}
```
由于現代的IDE提示和自動完成功能之強大,助手函數的作用非常有限,而且只會用助手函數對于框架的原理認識較淺,因此建議是掌握助手函數的內部實現原理后再來決定在項目規范中是否需要使用助手函數,以及如何使用。
畢竟有些場景下,助手函數是非常簡單實用的,例如:
```
public function getUser($id)
{
$user = User::getOrEmpty($id);
return json($user);
}
```
產品交付給客戶的時候,有些時候助手函數能夠讓客戶自定義模板的時候更方便。
如果你需要額外定義或者覆蓋原有的助手函數,可以直接在應用的`common.php`公共文件中定義。
## 路由規范
統一使用路由方法注冊路由而不要再使用返回數組配置,可以清晰直觀的看到每個路由規則的詳情,也便于開啟路由緩存。路由規則不區分大小寫,因此統一使用小寫定義。
盡量避免使用閉包定義路由規則(注意不要和分組路由的閉包定義搞混淆),否則無法使用路由緩存功能。
優先使用資源路由定義,在不適用資源路由的情況下也要多使用路由分組,不僅可以簡化路由定義和提高性能,也更加規范。
大部分情況下,建議開啟全局路由完整匹配,個別不需要完整匹配的路由規則可以在定義的時候使用`completeMatch`方法單獨關閉。
```
Route::get('user/<name>', 'user/info')->completeMatch(false);
```
如果需要使用偽靜態地址,可以全局配置URL訪問后綴,對于個別特殊后綴的路由可以在路由定義的時候單獨指定。
```
Route::get('hello/<name>', 'index/hello')->ext('htm');
```
明確你的路由變量規則,不要忽略路由變量的規則定義,避免可能的解析錯誤。例如,當你的路由變量中使用了小數點或者斜線的情況,必須嚴格定義你的變量規則。
優先在路由定義的時候指定中間件、進行數據驗證和請求緩存等操作,原則就是在路由里面能做的事情盡量提前不要等到控制器里面才執行。
為了方便查看當前項目定義的路由規則,可以使用下面的指令生成路由規則查看文件。
```
php think route:list
```
然后可以在`runtime`目錄下的`route_list.php`可以查看所有的路由列表,可以參考這篇:[命令行的表格輸出](https://blog.thinkphp.cn/754434)。
更多的路由使用技巧可以參考:[路由使用心得技巧](https://blog.thinkphp.cn/868952)。
## 控制器規范
為了避免命名沖突,可以統一開啟類庫后綴。
優先使用資源控制器,可以通過命令行快速生成一個資源控制器類
```
php think make:controller index/Blog
```
控制器建議繼承一個公共的控制器類,便于統一調整和增加通用邏輯。并建議繼承系統的控制器類,以便于使用控制器中間件功能。
對于控制器操作方法的攔截以及統一處理應當使用中間件獨立操作。
控制器的代碼應當盡量少,以確保邏輯清晰和可讀性。始終保持`controller`層作為訪問控制器層的名稱。
請求數據的驗證操作統一使用驗證器進行驗證。
操作方法中的對象使用依賴注入,其它的必要參數使用參數自動綁定。
不要在操作方法中輸出除了調試信息之外的任何內容,而是通過`return`返回需要輸出的內容。
操作方法中始終明確響應輸出的類型,而不要依賴全局配置。
## 數據庫和模型規范
### 基本規范
* 主鍵統一使用`id`;
* 外鍵統一使用`resource_id`形式(例如`user_id`);
* 模型數據字段統一使用小寫+下劃線命名,和數據表字段規范一致;
* 數據表統一添加系統時間字段(`create_time`和`update_time`),并使用`datetime`類型;
* 使用軟刪除并添加時間字段`delete_time`,類型和系統時間字段保持一致;
* 模型類應該繼承一個統一的公共類,便于調整和統一設置;
* 模型類應當通過定義`autoWriteTimestamp`屬性明確時間字段類型;
### 查詢規范
不要在數據庫配置文件以外的地方配置或者動態設置數據庫連接信息,包括模型內部也應該僅使用配置參數名定義不同的數據庫連接。
盡量不使用原生SQL查詢,而應當使用查詢構造器。
不要使用任何數據庫工具創建、修改數據表和填充數據,應當使用[數據遷移](http://www.hmoore.net/thinkphp/master-database-and-model/265553)并同步版本庫給所有成員。
每次數據查詢都用`Db`類或者模型類的靜態方法。
避免在模型方法中直接寫復雜的查詢條件,而應當使用查詢范圍或者搜索器統一定義后調用。用查詢表達式方式替代傳統的數組查詢。
查詢數據的處理統一使用獲取器定義,而不要直接處理數據。
對寫入數據需要額外處理的話統一使用修改器。
對于使用了SQL函數的用法,使用`fieldRaw`、`orderRaw`和`whereRaw`/`whereExp`替代`field`、`order`和`where`用法。
僅在使用字符串查詢條件,以及調用`whereExp`和`whereRaw`方法的時候需要使用手動參數綁定,其余情況下都會自動進行參數綁定,也不要手動調用`bind`方法。
不要在WEB訪問的時候進行大量數據操作,容易超時的數據處理應當在命令行下通過創建指令完成。
更多的使用技巧可以參考:[提高開發效率的查詢技巧](https://blog.thinkphp.cn/848639)以及[模型關聯查詢不完全指南](https://blog.thinkphp.cn/852701)。
## 是否需要模型分層
一般情況下,僅僅使用Model層已經夠用,但如果項目比較大,建議對模型進行分層,例如使用數據層、邏輯層和服務層等等,視項目需求而定,原則就是避免某一層過大導致結構雜亂,盡量讓各個層分工明確,各司其職。
## 模板規范
* 模板文件應當使用操作方法轉換為小寫+下劃線方式命名;
* 當你需要跨模塊調用的時候,盡量在控制器操作方法中明確要渲染的模板;
* 避免在模板文件中添加邏輯代碼,應當只是數據的輸出;
* 盡量避免在模板文件中添加樣式和JS代碼,不得已的時候必須使用`{literal} {/literal}`包含起來;
* 使用`static`目錄統一存放靜態資源文件;
## 日志規范
確保設置日志的最大數量限制,避免日志空間過大。
```
'max_files' => 30
```
超過設置的數量后,最早的日志將會被自動清理。
如果需要把日志接入阿里云,可以設置為單一日志文件,具體可以參考:[thinkphp日志接入阿里云日志系統](http://www.hmoore.net/xieyongfa123/thinkphp_note/852704)
更多日志使用建議參考:[如何更有效的記錄和管理日志](https://blog.thinkphp.cn/817547)。
## 命令行規范
* 相關緩存指令應當在部署到服務器后執行;
* 項目的指令應當添加獨立的指令空間,例如 `php think app:command_name`;
* 在`command.php`定義命令行指令列表的時候使用 “指令名 => 完整的類名”方式,提高性能;
## 寫更健壯的代碼
安全問題不容忽視,參考官方發布的[安全規范指引](https://blog.thinkphp.cn/789333),提前做好安全防范,讓你的項目更健壯。同時也要關注官方的[開發者周刊](http://www.hmoore.net/thinkphp/weekly/content)和微信公眾號,及時獲取官方的安全更新通告。
## 做好應用優化工作
參考[如何有效提高ThinkPHP的應用性能](https://blog.thinkphp.cn/843679)一文做好相關優化工作。
## 使用持續集成/持續部署構建你的項目
如果條件允許,請使用[持續集成/持續部署](https://blog.csdn.net/sinat_35930259/article/details/79429743),并添加自動化測試。[Travis CI](https://travis-ci.org/)或者[PHPCI](https://www.phptesting.org/)都是不錯的選擇。
## 編寫項目文檔
每個項目都應該在根目錄添加`readme.md` 文件,并遵循`Markdown`規范寫作,對項目做簡要的說明(尤其是目錄和代碼規范),如果項目比較復雜,可以附上一個項目詳細說明或者規范的文檔地址(托管到[看云文檔平臺](http://www.hmoore.net)上是一個很好的選擇),如果你的項目是前后端完全分離開發的話,應該事先規劃好后臺的API接口,然后在看云上創建一個**API文檔**,便于指導前端開發人員進行接口調用,以及方便在線調試。
- 值得升級到5.1的18個理由
- 5.1.7版本新特性
- JSON字段類型在ORM中的使用
- 文件下載響應對象
- 教你使用5.1的數組對象查詢
- 模型三大利器之一:搜索器
- 在ThinkPHP中使用Yaconf
- 掌握命令行的表格輸出
- 5.1.25查詢參數綁定的改進
- ThinkPHP安全規范指引
- 巧用數據集的排序功能實現統計排序
- think-orm ——基于5.1的獨立ORM庫
- think-template——基于ThinkPHP的獨立模板引擎
- ThinkPHP5.1.26版本發布——修正版本,包含安全更新
- ThinkPHP5.0和3.2再發安全更新
- 官宣:ThinkPHP發布首個LTS版本
- 你真的了解Db類和模型的正確使用姿勢么?
- 如何更有效的記錄和管理日志
- 模型三大利器之二:修改器
- ThinkPHP5.1.28版本發布——修正上一版本問題,改進關聯查詢
- 模型三大利器之三:獲取器
- API版本控制的幾種思路
- ThinkPHP5.2第一個Beta版本發布測試
- 讓你少犯錯的數據查詢基本原則
- ThinkPHP發布5.1.29版本——常規更新
- 這15個好習慣讓你更容易升級到5.2
- 如何有效提高ThinkPHP的應用性能
- 讓你提高開發效率的查詢技巧
- 模型關聯查詢不完全指南
- 5.2發布Beta2版本——統一和精簡大量用法
- ThinkPHP發布5.1.30版本——支持微秒時間字段寫入
- ThinkPHP的數據緩存使用
- ThinkPHP5.2安裝及入口文件
- ThinkPHP榮獲2018 年度最受歡迎中國開源開發框架第1名
- 5.1路由使用心得技巧
- ThinkPHP5.*版本發布安全更新
- ThinkPHP項目及代碼規范指北
- 5.2版本的設計規范指導
- ThinkPHP5.1.32版本發布——圣誕快樂
- 利用Trait特性給模型增加樂觀鎖功能
- 5.2數據庫和模型的變化(摘要)
- ThinkPHP模板引擎實現和常見問題
- ThinkPHP5.0.24版本發布——安全更新
- 不忘初心,方得始終——ThinkPHP十三周年報告
- ThinkPHP5+相關資源匯總
- 異步社區ThinkPHP周年慶專享優惠活動
- 5.2路由的調整和改進
- ThinkPHP發布5.1.33版本——包含安全更新
- ThinkPHP擴展開發指南
- ThinkPHP發布5.2Beta3版本
- ThinkPHP發布5.1.34版本——喜迎新年
- ThinkPHP發布5.2RC1版本
- ThinkPHP發布5.1.35版本——常規更新
- 5.2配置類的調整
- 5.2時間查詢的改進和優化
- 5.2RC版本升級不完全指導(僅供學習參考)
- ThinkPHP5.2版本正式變更為6.0版本
- ThinkPHP百度云云虛擬主機專享免費活動
- 事件系統以及查詢事件、模型事件的使用
- ThinkPHP6.0RC2版本發布——架構升級、精簡核心
- ThinkPHP5.1.36LTS版本發布——常規更新
- 新版Session和Cookie設計變化
- ThinkPHP5.1.37版本發布——常規更新
- ThinkPHP6.0RC3版本發布——細節完善,體驗優化
- 6.0中間件使用詳解
- Composer各大廠商鏡像地址
- ThinkPHP6.0發布計劃公告
- 「ThinkPHP開發者周刊」招募志愿者
- ThinkPHP6.0日志變化
- ThinkPHP5.1.38版本發布——常規更新
- ThinkPHP6.0RC4版本發布——ORM獨立,日志多通道支持
- ThinkORM2.0開發指南上線
- ThinkPHP6.0RC5版本發布——多應用模式獨立,中間件機制調整
- ThinkPHP6.0版本發布——程序員節福利
- ThinkPHP5.1.39LTS版本發布——常規更新
- ThinkPHP6.0.1版本發布——圣誕快樂!
- 回顧2019,展望2020!
- ThinkPHPV6.0.2版本發布——2020新春快樂!
- 周年福利系列:Swoole合作優惠
- 億速云成為ThinkPHPV6.0獨家贊助發布商??
- 新冠疫情工具和限免資源專題(保持更新中)
- 周年福利系列:創宇信用認證合作優惠
- 周年福利系列:碼云企業版限時10%優惠
- 周年福利系列:想天短說抵現優惠
- think-swoole直播:從零開始掌握swoole開發
- 周年福利系列:B2C開源電商ShopXO授權8折優惠
- 周年福利系列:LayuiAdmin 永久授權限時優惠
- ThinkPHP資源導航站上線——構建生態 服務未來
- ThinkPHP官方技術支持服務和應用服務市場上線公測
- ThinkPHP市場精選——推廣基本要素
- ThinkPHP市場精選——客服聊天專題
- ThinkPHPV6.0.3版本發布——端午安康
- ThinkPHP開發者扶持計劃
- 6.0.3版本關鍵更新及升級事項
- 「ThinkPHP開發者周刊」改版重啟
- ThinkPHP市場精選——企業建站專題
- ThinkPHP 提供統一API接口服務
- ThinkPHP市場精選——直播電商專題
- ThinkAPI服務SDK發布
- 官方服務市場啟用獨立子域名
- ThinkPHP市場精選——刷臉支付專題
- ThinkAPI推出會員服務計劃
- ThinkPHPV6.0.4版本發布——中秋國慶雙節快樂
- ThinkPHPV5.1.40版本發布——常規更新
- 1024程序員節福利走一波
- ThinkPHP V6.0.5版本發布——兼容Composer2.0
- 知識圖譜應用場景——源論技術沙龍
- ThinkPHP5.*版本改進Composer2.0的兼容
- 官方市場雙十一精選推薦
- 技術人做產品有機會么(文末送課程)
- 本周秒殺——古德云售后獲客營銷系統
- ThinkAPI服務更新——支持接口分組和PHP版本依賴調整
- PHP8新特性盤點
- PHP8新特性系列:構造器屬性提升使用及注意事項
- ThinkPHP2021新年寄語
- ThinkPHP V6.0.6&V5.1.41版本發布——兼容PHP8.0
- PHP如何更優雅地調用API接口
- ThinkPHP V6.0.7發布——修正版本
- ThinkAPI服務更新——IP白名單
- 最新版ThinkORM對于時間字段的調整
- ThinkAPI短信接口正式上線
- ThinkPHP V6.0.8版本發布——多環境變量配置支持
- 頂想云寫作服務開啟第一次公測
- ThinkSSL上線——官方SSL/TLS證書服務
- MDBootstrap國內用戶福利——ThinkPHP官方市場首發
- ThinkPHP V6.0.9版本發布——常規更新
- ThinkORM功能盤點——虛擬模型
- 全面支持主流GIT版本庫——云寫作服務第二次公測
- 云寫作服務私有化部署方案之:版本庫私有化
- 看云雙十一活動
- ThinkPHP V6.0.10LTS發布——兼容PHP8.1
- ThinkPHP V6.0.12發布——命令行兼容8.1
- 頂想云知識管理上線公測——構建企業文檔中心和知識庫
- 頂想云上線——助力生態數字化建設
- 618活動進行中——官方市場迎來一波更新
- 頂想云知識管理正式上線——看云文檔啟動遷移服務
- ThinkPHP V6.0.13發布——常規更新
- 頂想云網站助理服務上線——構建產品支持服務
- ThinkPHP發布6.1.0&6.0.14版本——安全更新
- ThinkPHP新版社區上線試運營
- ThinkAPI上架人臉核身接口——助力網站實名認證
- 辭舊迎新——舊版社區停止注冊及發帖
- ThinkPHP6.1.2版本發布——兼容PHP8.2