版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
ThinkPHP開發(fā)指北目錄1-ThinkPHP開發(fā)指北(零)序言2-ThinkPHP開發(fā)指北(一)規(guī)范篇3-ThinkPHP開發(fā)指北(二)優(yōu)化篇4-ThinkPHP開發(fā)指北(三)安全篇ThinkPHP開發(fā)指北(零)序言提供了一系列的開發(fā)規(guī)范、優(yōu)化建議和安全指南,同時也是對官方的完全開發(fā)手冊的一些總結(jié)和補(bǔ)充ThinkPHP誕生已經(jīng)超過18年了,很慶幸仍然處于活躍狀態(tài),并且有無數(shù)的PHP開發(fā)者和產(chǎn)品在使用。而且隨著技術(shù)的不斷進(jìn)步,官方也在不斷地更新迭代。作為一個成熟穩(wěn)定的中文PHP框架,ThinkPHP擁有著豐富的開發(fā)組件和大量的第三方學(xué)習(xí)資料,為開發(fā)者提供了入門便利。本《開發(fā)指北》系列文章旨在從官方的角度幫助開發(fā)者更好地使用ThinkPHP,提供了一系列的開發(fā)規(guī)范、優(yōu)化建議和安全指南,同時也是對官方的完全開發(fā)手冊的一些總結(jié)和補(bǔ)充,無論是初學(xué)者還是有一定經(jīng)驗的開發(fā)者,都能從本系列文章中獲得實用的知識和技巧,提升自己的開發(fā)水平和效率。具體開發(fā)過程中涉及到具體的使用仍然建議查詢官方提供的\h開\h發(fā)手冊。本系列文章主要針對ThinkPHP8.0版本,但大部分內(nèi)容仍然適用于6.1或之前版本。本系列文章分為三篇:\h(一)規(guī)范篇\h(二)優(yōu)化篇\h(三)安全篇PHP版本選擇如果是新的項目,目前應(yīng)該盡量選擇PHP8.2+作為你的PHP版本,可以擁有更好的性能,ThinkPHP8.0版本的最低版本要求是PHP8.0。有些PHP擴(kuò)展可能不支持PHP的高版本,這個時候你要做出選擇,使用低版本還是尋\hThinkPHP知識庫ThinkPHP版本選擇如果是全新的項目開發(fā),建議使用最新的8.0版本,該版本基于PHP8.0重構(gòu)(會兼容PHP8.x),性能更優(yōu),如果你之前基于6.0或6.1版本開發(fā),也可以無縫升級到最新的8.0版本。并且注意下主要版本的生命周期,并盡可能在完全更新結(jié)束之前升級到最新版本。ThinkPHP版本5.0(PHP5.4+)5.1(PHP5.6+)6.0(PHP7.1+)8.0(PHP8.0+)
發(fā)布時間2016年9月15日2018年1月1日2019年10月24日2023年6月30日
BUG修復(fù)2019年1月1日2020年1月1日2024年10月24日2025年6月30日
安全更新2020年1月1日2021年1月1日2024年10月24日2026年6月30日如果你還在使用5.1或更早的版本,可以參考官方\h的升級指導(dǎo)先升級到6.1,然后再升級到8.0即可。依賴管理在PHP生態(tài)中,\hComposer是最先進(jìn)的依賴管理方案,通過Composer你可以安裝很多優(yōu)秀的\h生態(tài)擴(kuò)展,你可以在\hPackagist搜索更多的庫。如果你沒有使用Composer來管理應(yīng)用的依賴,最終會導(dǎo)致應(yīng)用里某個依賴會嚴(yán)重過時或出現(xiàn)兼容性問題,開發(fā)過程中時常記得保持依賴的更新。composerupdateThinkPHP開發(fā)指北(一)規(guī)范篇總結(jié)了ThinkPHP開發(fā)過程中的一些規(guī)范和建議本篇主要總結(jié)了ThinkPHP開發(fā)過程中的一些規(guī)范和建議,當(dāng)然除了代碼規(guī)范,或許更應(yīng)該關(guān)注下\h代碼簡潔之道。命名規(guī)范ThinkPHP遵循PSR-2命名規(guī)范以及PSR-4自動加載規(guī)范,并注意如下規(guī)范:如果你沒有遵循某些規(guī)范,可能會導(dǎo)致部分功能的異常。類和文件命名類(包括接口、rait)文件名和類名保持一致,并且使用首字母大寫的駝峰命名;函數(shù)文件、配置文件、路由定義文件等文件名使用小寫規(guī)范;無論類還是普通文件都使用.php后綴;目錄名統(tǒng)一使用小寫規(guī)范,并且使用單數(shù)規(guī)范;模板文件使用小寫規(guī)范;配置和變量命名配置參數(shù)名統(tǒng)一使用小寫規(guī)范;常量定義統(tǒng)一使用大寫規(guī)范;環(huán)境變量定義統(tǒng)一使用大寫規(guī)范;函數(shù)和類、屬性命名\hThinkPHP知識庫屬性的命名使用駝峰法(首字母小寫),例如tableName、instance;特例:以雙下劃線__打頭的函數(shù)或方法作為魔術(shù)方法,例如__call和__callStatic;數(shù)據(jù)表命名數(shù)據(jù)表和字段采用小寫加下劃線方式命名,例如think_user表和user_name字段,禁止使用駝峰、中文或者拼音作為數(shù)據(jù)表及字段命名。字段規(guī)范主鍵統(tǒng)一使用id;外鍵統(tǒng)一使用resource_id形式(例如user_id);模型數(shù)據(jù)字段統(tǒng)一使用小寫+下劃線命名,和數(shù)據(jù)表字段規(guī)范一致;數(shù)據(jù)表統(tǒng)一添加系統(tǒng)時間字段(create_time和update_time),并使用datetime類型;使用軟刪除并添加時間字段delete_time,類型和系統(tǒng)時間字段保持一致;模型類應(yīng)該繼承一個統(tǒng)一的公共類,便于調(diào)整和統(tǒng)一設(shè)置;模型類應(yīng)當(dāng)通過定義autoWriteTimestamp屬性明確時間字段類型;其它數(shù)據(jù)庫規(guī)范不使用存儲過程,存儲過程難以調(diào)試和擴(kuò)展,更沒有移植性。不使用外鍵和級聯(lián),一切外鍵概念建議在應(yīng)用層解決。如果需要存儲emoji,使用utf8mb4使?統(tǒng)?的IDE以及代碼規(guī)范配置或者插件項目團(tuán)隊?wèi)?yīng)當(dāng)盡量使用統(tǒng)一的IDE作為開發(fā)工具,并規(guī)范一致的代碼規(guī)范配置項,包括使用統(tǒng)一的第三方代碼規(guī)范及自動完成插件。如果團(tuán)隊成員較多而無法完全統(tǒng)一,最低限度,項目代碼風(fēng)格必須遵循PSR-1和PSR-2規(guī)范。助?函數(shù)\hThinkPHP知識庫限,而且只會用助手函數(shù)對于框架的原理認(rèn)識較淺,因此建議是掌握助手函數(shù)的內(nèi)部實現(xiàn)原理后再來決定在項目規(guī)范中是否需要使用助手函數(shù),以及如何使用。畢竟有些場景下,助手函數(shù)是非常簡單實用的,例如:publicfunctiongetUser($id){$user=User::getOrEmpty($id);returnjson($user);}產(chǎn)品交付給客戶的時候,有些時候助手函數(shù)能夠讓客戶自定義模板的時候更方便。如果你需要額外定義或者覆蓋原有的助手函數(shù),可以直接在應(yīng)用的common.php公共文件中定義。配置規(guī)范線上環(huán)境和本地測試環(huán)境應(yīng)該使用一致的配置文件,差異化的配置使用環(huán)境變量方式處理。本地環(huán)境可以通過定義.env文件(注意添加到忽略文件列表)來模擬環(huán)境變量。在你需要差異化配置的參數(shù)中使用env函數(shù)定義,例如:'db_host' => env('db_host',''),然后在環(huán)境變量中或者本地.env中定義DB_HOST=2盡量不要在配置文件以外使用env函數(shù)獲取配置參數(shù)。統(tǒng)一使用config函數(shù)獲取配置參數(shù)。除了定義配置文件之外,避免使用動態(tài)配置功能,保持僅讀取配置參數(shù)的良好習(xí)慣。如果需要提高配置文件的性能,可以考慮使用Yaconf擴(kuò)展。安裝\hThinkPHP知識庫?志規(guī)范日志記錄建議直接使用PSR-3規(guī)范提供的接口方法記錄,例如:Log::record('測試日志','error');Log::record('測試日志','info');應(yīng)當(dāng)改為Log::error('測試日志');Log::info('測試日志');支持的方法包括debug, info, notice, warning, error, critical,alert, emergency以及用于SQL日志記錄的sql方法。默認(rèn)情況下,日志是延時寫入的,如果要實時寫入日志信息,可以使用write方法Log::wirte('測試日志','info');確保設(shè)置日志的最大數(shù)量限制,避免日志空間過大導(dǎo)致存儲空間占滿。'max_files' => 30超過設(shè)置的數(shù)量后,最早的日志將會被自動清理。如果需要把日志接入阿里云,可以設(shè)置為單一日志文件,具體可以參考\h:thinkphp日志接入\h阿里云日志系統(tǒng)規(guī)范部署請務(wù)必把你的WEB根目錄指向public目錄而不是應(yīng)用根目錄,并且不要隨意更改入口文件的位置。public目錄下面不要放除了入口文件和資源文件以外的其它應(yīng)用文件。\hThinkPHP知識庫在開發(fā)過程中,應(yīng)該盡量保持你的測試環(huán)境和正式部署環(huán)境的一致性,包括運(yùn)行環(huán)境和版本,無論在本地測試環(huán)境還是部署環(huán)境,都應(yīng)當(dāng)統(tǒng)一使用域名方式訪問,本地可以使用測試域名,例如你的正式部署域名為,那么本地測試環(huán)境可以使用thinkphp或者thinkphp.test作為測試域名,避免使用localhost或者這種測試地址。對于有多個域名的部署應(yīng)用,本地也要盡量模擬多個域名。關(guān)閉調(diào)試模式在部署到生產(chǎn)環(huán)境的時候,確保你已經(jīng)關(guān)閉了調(diào)試模式,可以通過修改環(huán)境變量的方式關(guān)閉調(diào)試模式。APP_DEBUG=false無論是本地開發(fā)還是生產(chǎn)環(huán)境部署,都建議保持統(tǒng)一的配置文件,然后通過修改環(huán)境變量的方式(本地開發(fā)可以通過定義.env文件)設(shè)置區(qū)別部分。關(guān)閉調(diào)試模式后,系統(tǒng)的健康狀態(tài)和運(yùn)行監(jiān)控主要依靠日志或者你使用的監(jiān)控服務(wù)。所以,要養(yǎng)成定時檢查日志和運(yùn)行狀態(tài)的習(xí)慣。部署忽略清單項目根目錄下面有一個.gitignore文件,用于定義提交版本庫的時候哪些文件或者目錄需要忽略,設(shè)置忽略的文件不會被同步到遠(yuǎn)程服務(wù)器,只是用于本地開發(fā)。該文件默認(rèn)內(nèi)容如下,你可以根據(jù)項目的目錄和規(guī)范進(jìn)行調(diào)整。/.idea/.vscode/vendor*.log.env項目使用的核心框架以及composer安裝的擴(kuò)展,不應(yīng)當(dāng)被同步到版本庫中,只需要同步composer.json以及composer.lock文件。然后在服務(wù)器端進(jìn)行composer更新。\hThinkPHP知識庫如果條件允許,請使用\h持續(xù)集成/持續(xù)部署,并添加自動化測試。\hTravisCI或\h者PHPCI都是不錯的選擇。編寫項?文檔每個項目都應(yīng)該在根目錄添加readme.md文件,并遵循Markdown規(guī)范寫作,對項目做簡要的說明(尤其是目錄和代碼規(guī)范),如果項目比較復(fù)雜,可以附上一個項目詳細(xì)說明或者規(guī)范的文檔地址(托管\h到頂想云知識管理上是一個很好的選擇),如果你的項目是前后端完全分離開發(fā)的話,應(yīng)該事先規(guī)劃好后臺的API接口,然后創(chuàng)建一個API文檔,便于指導(dǎo)前端開發(fā)人員進(jìn)行接口調(diào)用,以及方便在線調(diào)試。中間件中間件的主要應(yīng)用場景可以包括對HTTP請求的數(shù)據(jù)過濾、權(quán)限檢測、請求攔截等行為,使用中間件能夠讓控制器的定義更加簡單,很多額外的非核心業(yè)務(wù)流程的處理都可以交給中間件執(zhí)行,具體參考官方手冊\h的中間件。默認(rèn)安裝后的應(yīng)用是不支持Session的,你必須全局開啟Session初始化中間件后Session才能生效。對于API應(yīng)用來說,本身就不需要Session功能支持;在全局中間件定義的應(yīng)用中間件盡量確保系統(tǒng)中間件的優(yōu)先執(zhí)行;多應(yīng)用模式下,可以定義某個應(yīng)用中間件,僅在該應(yīng)用下有效;盡可能在路由或路由分組中使用中間件,提前攔截處理;對于常用的中間件可以定義中間件別名;路由規(guī)范所有的路由規(guī)則是不支持普通URL參數(shù)的,必須是PATHINFO地址。路由定義文件不一定是route.php,事實上可以是任何文件名。如果你開啟了路由強(qiáng)制模式,那么未定義的路由訪問將會拋出異常。統(tǒng)一使用路由方法注冊路由而不要再使用返回數(shù)組配置,路由規(guī)則不區(qū)分大小寫,因此統(tǒng)一使用小寫定義。盡量避免使用閉包定義路由規(guī)則(注意不要和分組路由的閉包定義搞混淆),優(yōu)先使用資源路由定義,在不適用資源路由的情況下也要多使用路由分組,不僅可以簡化路由定義和提高\(yùn)hThinkPHP知識庫大部分情況下,建議開啟全局路由完整匹配,個別不需要完整匹配的路由規(guī)則可以在定義的時候使用completeMatch方法單獨(dú)關(guān)閉。Route::get('user/<name>','user/info')->completeMatch(false);如果需要使用偽靜態(tài)地址,可以全局配置URL訪問后綴,對于個別特殊后綴的路由可以在路由定義的時候單獨(dú)指定。Route::get('hello/<name>','index/hello')->ext('htm');明確你的路由變量規(guī)則,不要忽略路由變量的規(guī)則定義,避免可能的解析錯誤。例如,當(dāng)你的路由變量中使用了小數(shù)點或者斜線的情況,必須嚴(yán)格定義你的變量規(guī)則。優(yōu)先在路由定義的時候指定中間件、進(jìn)行數(shù)據(jù)驗證和請求緩存等操作,原則就是在路由里面能做的事情盡量提前不要等到控制器里面才執(zhí)行。為了方便查看當(dāng)前項目定義的路由規(guī)則,可以使用下面的指令生成路由規(guī)則查看文件。phpthinkroute:list然后可以在runtime目錄下的route_list.php可以查看所有的路由列表。關(guān)閉路由如果某個應(yīng)用需要關(guān)閉路由功能,可以在應(yīng)用的app.php配置文件中定義'with_route' => false,但需要注意的是,即使關(guān)閉路由,也會走默認(rèn)路由(即控制器/操作)解析,因此路由全局中間件仍然有效。明確定義請求類型盡量明確定義路由的請求類型,提高路由解析的效率。推薦使用:\hThinkPHP知識庫替代:Route::rule('hello/:name','index/hello');不需要添加開頭斜線除了首頁外,其它路由規(guī)則定義不需要添加開頭的斜線。推薦使用:Route::get('hello/:name','index/hello');不建議使用:Route::get('/hello/:name','index/hello');除非是首頁路由Route::get('/','index/index');或者直接訪問分組名的情況Route::group('blog',function(){Route::get('/','index/blog');Route::get(':id$','blog/read');Route::get(':id/edit$','blog/edit');});多使?路由分組可能的情況下,盡可能多使用路由分組。可以充分利用分組的匹配機(jī)制提高路由解析性能。推薦使用\hThinkPHP知識庫Route::get(':id/edit$','blog/edit');});不建議使用Route::get('blog/:id$','blog/read');Route::get('blog/:id/edit$','blog/edit');路由分組傳入額外參數(shù)可以統(tǒng)一給分組路由傳入額外的參數(shù)Route::group('blog',function(){Route::get(':id$','blog/read');Route::get(':id/edit$','blog/edit');})->ext('html')->pattern(['id'=>'\d+'])->append(['group_id'=>1]);上面的分組路由統(tǒng)一傳入了group_id參數(shù),該參數(shù)的值可以通過Request類的param方法獲取。路由變量定義規(guī)范對于新版的路由變量定義來說,不再區(qū)分普通變量和組合變量,哪怕你使用:name方式定義,內(nèi)部也會統(tǒng)一轉(zhuǎn)換成<name>這種方式,因此為了提高路由解析性能,建議統(tǒng)一使用:Route::group('blog',function(){Route::get('<id>$','blog/read');Route::get('<id>/edit$','blog/edit');});盡量明確定義路由變量的規(guī)則\hThinkPHP知識庫Route::get('<id>/edit$','blog/edit');})->pattern(['id'=>'\d+']);路由變量規(guī)則采用正則表達(dá)式方式定義,但無需在開頭添加^或者在最后添加$,也無需使用模式修飾符,系統(tǒng)會自動添加。不能使用$_GET方法或者Request類的get方法獲取路由變量,而應(yīng)該使用param方法或者參數(shù)綁定。如果開啟了路由合并解析的話,分組下面的多個路由規(guī)則是通過一次解析匹配完成的,如果路由規(guī)則較多性能會有大幅提升。變量分隔符你可以很隨意的使用路由變量分隔符,只要注意不要和你的變量規(guī)則沖突。Route::get('item/<date><name>-<id>','product/item')->pattern(['date'=>'\d{8}','name'=>'\w+','id'=>'\d+']);默認(rèn)路由變量規(guī)則默認(rèn)情況下,如果你沒有定義變量規(guī)則,則使用\w+作為變量規(guī)則Route::get('hello/<name>','index/hello');其實等同于Route::get('hello/<name>','index/hello')->pattern(['name' => '\w+',]);如果你希望改變默認(rèn)的路由變量規(guī)則,可以在應(yīng)用配置文件中設(shè)置//默認(rèn)的路由變量規(guī)則\hThinkPHP知識庫路由完全匹配默認(rèn)的路由規(guī)則只是匹配URL地址的開頭是否和定義的路由匹配所以Route::get('hello/:name','index/hello');可以匹配下面的URL地址hello/thinkhello/think/thinkphphello/think/thinkphp/demo但如果添加了路由完全匹配后Route::get('hello/:name$','index/hello');上面的三個URL地址中就只會匹配hello/think建議你開啟全局路由完全匹配//路由完全匹配'route_complete_match'=>true,如果有個別路由仍然希望不要完全匹配,你可以使用Route::get('hello/:name','index/hello')->completeMatch(false);關(guān)閉當(dāng)前路由規(guī)則(或者路由分組)的完整匹配。\hThinkPHP知識庫路由標(biāo)識的作用只是用于URL地址生成,而且默認(rèn)會使用當(dāng)前的路由地址作為路由標(biāo)識。Route::get('hello/:name','index/hello');echourl('index/hello',['name'=>'think']);如果指定了路由標(biāo)識的話,url方法的用法就需要調(diào)整為:Route::get('hello/:name','index/hello')->name('hello');echourl('hello',['name'=>'think']);如果你希望簡化URL地址的生成調(diào)用,可以在項目規(guī)范中強(qiáng)制統(tǒng)一規(guī)范,而不要使用URL地址這種默認(rèn)標(biāo)識,使用路由標(biāo)識的優(yōu)勢是即使路由地址發(fā)生了變化,也無需改變url方法的代碼。??法定義路由參數(shù)出于語義化考慮,路由參數(shù)建議使用方法而不是參數(shù)。推薦使用(支持IDE)Route::get('new/:id','News/read')->ext('html')->https();不建議使用:Route::get('new/:id','News/read')->option(['ext'=>'html','https'=>true]);MISS路由一旦你設(shè)置了全局的MISS路由,相當(dāng)于開啟了強(qiáng)制路由模式。Route::miss('public/miss');MISS路由可以針對不同路由分組(或者域名)設(shè)置,也可以針對不同的請求類型設(shè)置,\hThinkPHP知識庫...Route::miss('blog/error','get');Route::miss('blog/noAuth','post');});Route::group('user',function(){Route::get(':id','user/info');...Route::miss('user/error');});跨域請求?持如果需要支持跨域,可以使\h用think-cors跨域擴(kuò)展,支持配置來源域名和路徑。當(dāng)配置中有*時,代表不限制來源域。['allowed_origins'=>['*'],]當(dāng)我們需要限制來源域時,可以寫成。['allowed_origins'=>['',''],]可以為不同的域名配置跨域路徑['paths'=>[''=>['api/*'],''=>['user/*','article/*'],]]\hThinkPHP知識庫為了避免命名沖突,可以在路由配置文件中統(tǒng)一開啟控制器類庫后綴。'controller_suffix' =>true,優(yōu)先使用資源控制器,可以通過命令行快速生成一個資源控制器類phpthinkmake:controllerBlog控制器建議繼承一個公共的控制器類,便于統(tǒng)一調(diào)整和增加通用邏輯。默認(rèn)安裝后,系統(tǒng)提供了一個app\BaseController實例基礎(chǔ)控制器類,你可以根據(jù)自己項目的需求進(jìn)行調(diào)整,包括改變命名空間。對于控制器操作方法的攔截以及統(tǒng)一處理應(yīng)當(dāng)使用控制器中間件獨(dú)立操作,原來的初始化方法已經(jīng)廢棄??刂破髦虚g件不需要繼承任何的基礎(chǔ)控制器類即可使用,僅僅需要你定義middleware屬性即可??刂破鞯拇a應(yīng)當(dāng)盡量少,以確保邏輯清晰和可讀性。并始終保持controller層作為訪問控制器層的名稱。請求數(shù)據(jù)的驗證操作統(tǒng)一使用驗證器進(jìn)行驗證。操作方法中的對象使用依賴注入,其它的必要參數(shù)使用參數(shù)自動綁定。不要在操作方法中輸出除了調(diào)試信息之外的任何內(nèi)容,而是通過return返回需要輸出的內(nèi)容。操作方法中始終明確響應(yīng)輸出的類型,默認(rèn)的return方式使用的是HTML輸出類型。查詢規(guī)范一些基本規(guī)范如下:不要在數(shù)據(jù)庫配置文件以外的地方配置或者動態(tài)設(shè)置數(shù)據(jù)庫連接信息,包括模型內(nèi)部。盡量不使用原生SQL查詢,而應(yīng)當(dāng)使用查詢構(gòu)造器。不要使用任何數(shù)據(jù)庫工具創(chuàng)建、修改數(shù)據(jù)表和填充數(shù)據(jù),應(yīng)當(dāng)使\h用數(shù)據(jù)遷移并同步版本庫給所有成員。每次數(shù)據(jù)查詢都用Db類或者模型類的靜態(tài)方法。\hThinkPHP知識庫查詢數(shù)據(jù)的處理統(tǒng)一使用獲取器定義,而不要直接處理數(shù)據(jù)。對寫入數(shù)據(jù)需要額外處理的話統(tǒng)一使用修改器。對于使用了SQL函數(shù)的用法,使用fieldRaw、orderRaw和whereRaw/whereExp替代field、order和where用法。僅在使用字符串查詢條件,以及調(diào)用whereExp和whereRaw方法的時候需要使用手動參數(shù)綁定,其余情況下都會自動進(jìn)行參數(shù)綁定,禁止手動調(diào)用bind方法。不要在WEB訪問的時候進(jìn)行大量數(shù)據(jù)操作,容易超時的數(shù)據(jù)處理應(yīng)當(dāng)在命令行下通過創(chuàng)建指令完成。查詢值為Null的數(shù)據(jù)查詢值為Null的數(shù)據(jù)應(yīng)當(dāng)使用whereNull或者whereNotNull方法//查詢email為空,并且name不為空的用戶數(shù)據(jù)User::whereNull('email')->whereNotNull('name')->select();使?快捷?法對于一些常用的查詢,盡量使用系統(tǒng)封裝的快捷查詢方法,例如:User::whereIn('id',[1,2,3])->whereLike('name','think%')->select();相當(dāng)于下面的查詢User::where('id','in',[1,2,3])->where('name','like','think%')->select();更多的方法可以參考官方手冊或者使用IDE的自動提示。\hThinkPHP知識庫對于一些簡單的數(shù)據(jù)獲取,你完全不需要查詢整個表的數(shù)據(jù),例如查詢某個字段(滿足條件的)值或者列數(shù)據(jù)。//獲取id為10的用戶名稱User::where('id',10)->value('name');//獲取狀態(tài)為1的用戶名稱列表User::where('status',1)->column('name');//獲取分?jǐn)?shù)大于80的用戶分?jǐn)?shù)列表,以用戶ID為索引User::where('score','>',80)->column('score','id');聚合查詢?nèi)绻愕膍in/max查詢的是一個字符串類型字段,記得加上第二個參數(shù)并傳入false。//獲取name字段的最大值User::max('name',false);時間區(qū)間查詢時間查詢主要用于時間字段的區(qū)間查詢,whereTime方法的優(yōu)勢是支持自動識別時間字段類型并進(jìn)行轉(zhuǎn)換處理。//大于某個時間User::whereTime('birthday','>=','2008-10-1')->select();//小于某個時間User::whereTime('birthday','<','2000-10-1')->select();//時間區(qū)間查詢User::whereBetweenTime('birthday','1990-10-1','2000-10-1')->select();//不在某個時間區(qū)間\hThinkPHP知識庫年/?/?/周查詢對于年/月/日/周的時間查詢,推薦使用whereYear/whereMonth/whereDay/whereWeek方法查詢,例如://查詢本月注冊的用戶Db::name('user')->whereMonth('create_time')->select();//查詢上月注冊用戶Db::name('user')->whereMonth('create_time','lastmonth')->select();//查詢2018年6月注冊的用戶Db::name('user')->whereMonth('create_time','2018-06')->select();//查詢當(dāng)天注冊的用戶Db::name('user')->whereDay('create_time')->select();//查詢昨天注冊的用戶Db::name('user')->whereDay('create_time','yesterday')->select();//查詢2018年6月1日注冊的用戶Db::name('user')->whereDay('create_time','2018-06-01')->select();時間表達(dá)式查詢高級的時間表達(dá)式查詢可以使用PHP的\h相對時間格式,例如:\hThinkPHP知識庫->select();//查詢昨天中午后發(fā)的博客Blog::whereTime('create_time','yesterdaynoon')->select();更多的時間表達(dá)式查詢你可以自由發(fā)揮。時間字段范圍查詢你可以查詢當(dāng)前時間是否在兩個時間字段區(qū)間范圍內(nèi),通常用于一些活動以及優(yōu)惠券的有效期查詢等等。//查詢有效期內(nèi)的活動Event::whereBetweenTimeField('start_time','end_time')->select();//查詢沒有開始或者已經(jīng)過期的活動Event::whereNotBetweenTimeField('start_time','end_time')->select();字段比較可以直接比較兩個字段的大小進(jìn)行查詢User::whereColumn('update_time','>','create_time')->select();User::whereColumn('score1','>','score2')->select();如果需要比較兩個字段相同,可以使用User::whereColumn('score1','score2')->select();\hThinkPHP知識庫應(yīng)當(dāng)使用條件查詢替代在組裝查詢條件的時候?qū)懘罅康膇f和else。User::when($condition,function($query){//滿足條件后執(zhí)行$query->where('score','>',80)->limit(10);})->select();并且支持不滿足條件的分支查詢,并且支持多次調(diào)用when方法。User::when($condition,function($query){//滿足條件后執(zhí)行$query->where('score','>',80)->limit(10);},function($query){//不滿足條件執(zhí)行$query->where('score','>',60);})->select();JSON查詢?nèi)绻愕淖侄晤愋褪褂玫氖荍SON類型,那么可以直接使用框架提供的JSON查詢支持。User::where('info->nickname','ThinkPHP')->find();注意,需要在模型里面定義JSON字段屬性。<?phpnamespaceapp\index\model;usethink\Model;classUserextendsModel{//設(shè)置json類型字段protected$json=['info'];}\hThinkPHP知識庫$user=Db::name('user')->json(['info'])->where('info->nickname','ThinkPHP')->find();SQL函數(shù)查詢?nèi)绻枰獙δ硞€字段使用SQL函數(shù)表達(dá)式查詢,可以使用User::whereExp('nickname',"=CONCAT(name,'-',id)")->whereRaw('LEFT(nickname,5)=?',['think'])->select();注意whereExp和whereRaw方法的區(qū)別,前者是對某個字段使用SQL函數(shù)表達(dá)式,后者是整個查詢就是一個SQL函數(shù)表達(dá)式。字段遞增/遞減可以使用://博客的閱讀數(shù)遞增1評論數(shù)遞減2Blog::where('id',10)->inc('read_count')->dec('comment_count',2)->save();新版已經(jīng)取消了延時更新功能。指定字段值排序如果你需要按照指定字段的值的順序來排序,可以使用User::where('status',1)->orderField('id',[1,2,3])\hThinkPHP知識庫從主庫讀取如果你使用了數(shù)據(jù)庫的主從分離,當(dāng)剛寫入數(shù)據(jù)后,數(shù)據(jù)庫的主從同步可能還沒來得及同步,這個時候立刻查詢數(shù)據(jù)可能會出錯,你可以使用下面的方法從主庫讀取。$user=User::create($data);$user->readMaster()->select();你可以全局配置數(shù)據(jù)寫入后自動讀取主庫//模型寫入后自動讀取主服務(wù)器'read_master' =>true,獲取?增ID使用Db類的insert方法或者模型的save方法返回的不是自增主鍵,不過你可以使用。$userId=Db::name('user')->insertGetId($data);如果使用模型的話,自增主鍵的值會自動賦值給模型對象,可以直接獲取。$user=User::create($data);echo$user->id;模型查詢?yōu)榭盏奶幚砟P筒樵償?shù)據(jù)不存在的話返回值為Null,所以必須要添加返回值判斷然后進(jìn)行數(shù)據(jù)處理,建議使用下面的方法查詢,如果數(shù)據(jù)不存在則返回空的模型對象。//始終返回模型對象$user=User::where('id',10)->findOrEmpty();\hThinkPHP知識庫如果你需要一次寫入大量數(shù)據(jù),建議使用limit方法自動分批多次寫入。//自動分批多次寫入數(shù)據(jù)庫每次最多寫入1000條Db::name('user')->limit(1000)->insertAll($dataList);如果是使用模型的話,建議直接使用saveAll方法而不需要limit方法。$user=newUser;$user->saveAll($dataList);數(shù)據(jù)分批處理對于大量數(shù)據(jù)的處理操作,建議使用chunk分批處理方法。//每次處理100個數(shù)據(jù)User::chunk(100,function($users){foreach($usersas$user){//處理數(shù)據(jù)}});游標(biāo)查詢對于內(nèi)存開銷比較大的應(yīng)用,在做大量數(shù)據(jù)查詢和處理的時候,建議使用cursor方法進(jìn)行游標(biāo)查詢,可以利用PHP的生成器特性,減少內(nèi)存占用。$cursor=User::cursor();foreach($cursoras$user){//處理數(shù)據(jù)}關(guān)聯(lián)查詢是否需要模型分層一般情況下,僅僅使用Model層已經(jīng)夠用,但如果項目比較大,建議對模型進(jìn)行分層,例如使用數(shù)據(jù)層、邏輯層和服務(wù)層等等,視項目需求而定,原則就是避免某一層過大導(dǎo)致結(jié)構(gòu)雜亂,盡量讓各個層分工明確,各司其職。ThinkPHP開發(fā)指北(二)優(yōu)化篇框架并不是應(yīng)用性能的瓶頸,架構(gòu)設(shè)計、數(shù)據(jù)庫和人才是首先要強(qiáng)調(diào)一點:框架并不是應(yīng)用性能的瓶頸,架構(gòu)設(shè)計、數(shù)據(jù)庫和人才是??蚣茉谠O(shè)計之初,出于通用性考慮,不會特意針對某個應(yīng)用做深入架構(gòu)優(yōu)化架構(gòu)優(yōu)化涉及到技術(shù)、存儲、網(wǎng)絡(luò)、服務(wù)的選型和構(gòu)架,盡量使用成熟和現(xiàn)代的開發(fā)架構(gòu)和設(shè)計模式。前后端完全分離設(shè)計,便于前后端的獨(dú)立如果你的應(yīng)用遇到了性能瓶頸,這個時候要考慮的就是優(yōu)化架構(gòu)而不是優(yōu)化代碼本身,因為架構(gòu)層面的優(yōu)化效果往往是最顯著的。架構(gòu)的優(yōu)化需要根據(jù)自身運(yùn)營情況來調(diào)整,切忌不可按圖索驥提前優(yōu)化,反而容易得不償失,導(dǎo)致技術(shù)成本提高甚至“負(fù)優(yōu)化”。關(guān)閉調(diào)試模式部署環(huán)境千萬不要忘記關(guān)閉調(diào)試模式,這不僅僅是出于性能考慮,更多是基于安全因素。事實上,建議通過環(huán)境變量來配置關(guān)閉調(diào)試模式,這樣因為調(diào)試模式影響日志記錄信息、額外的調(diào)試信息和緩存失效,關(guān)閉調(diào)試模式能夠帶來很大程度的性能提升。使?單應(yīng)?模式雖然6.0+版本開始,ThinkPHP提供了多應(yīng)用模式來替代早期版本的多模塊功能,但多應(yīng)用功能是作為擴(kuò)展提供,并非內(nèi)置,之所以這樣設(shè)計使用單應(yīng)用模式,然后使用控制器分級來解決控制器過多的問題。從部署優(yōu)化和架構(gòu)趨勢來說,仍然建議使用默認(rèn)的單應(yīng)用模式更佳。使用單應(yīng)用的性能優(yōu)勢,在部署到swoole的時候可以得到更加充分的體現(xiàn),由于某些原因,think-swoole對多應(yīng)用的支持尚不夠完善。路由設(shè)計及優(yōu)化路由的設(shè)計和定義對于應(yīng)用來說至關(guān)重要,路由環(huán)節(jié)的優(yōu)化能帶來請求效率的提升和避免在控制器層耗費(fèi)不必要的資源。在定義路由規(guī)則的時候,不要使用數(shù)組方式,盡量使用方法注冊路由,并且多使用路由分組(或者資源路由)。分組路由可以減少路由的匹配次盡可能設(shè)計在路由中進(jìn)行當(dāng)前路由的數(shù)據(jù)驗證和權(quán)限檢查等操作,一方面比較清晰,另外一方面可以盡量把驗證操作提前,而不必等到控制器執(zhí)在分組比較多的情況下,開啟路由的延遲解析,是實際匹配到分組后才會進(jìn)行分組下的路由解析。//開啟路由延遲解析'url_lazy_route' =>true,如果同一個分組下面有比較多的路由規(guī)則,建議合并路由規(guī)則。//合并分組路由規(guī)則'route_rule_merge' =>true,對于GET請求的路由,如果不涉及到實時的權(quán)限判斷可以設(shè)置路由的請求緩存。//定義GET請求路由規(guī)則并設(shè)置3600秒的緩存Route::get('new/:id','News/read')->cache(3600);首先保持良好的開發(fā)習(xí)慣,數(shù)據(jù)庫本身的性能優(yōu)化可以參考\hMySQL性能優(yōu)化的最佳21條經(jīng)驗,下面主要是對框架中數(shù)據(jù)查詢相關(guān)的優(yōu)化策略。開啟查詢性能分析框架不但能記錄SQL日志,而且可以對查詢的SQL語句作出性能分析,幫助你快速找出數(shù)據(jù)庫性能瓶頸。確保在數(shù)據(jù)庫配置文件中開啟下面兩個參數(shù)://開啟數(shù)據(jù)庫調(diào)試模式'debug' =>true,//開啟SQL性能分析'sql_explain' =>true,開啟sql_explain參數(shù)后,會對查詢的SQL做EXPLAIN解析(由每個連接器類的getExplain方法完成查詢SQL分析),并把解析結(jié)果下面是一個查詢的分析日志例子:[SQL]SELECT*FROM`user`WHERE`id`IN(2)[RunTime:0.000703s][EXPLAIN:array('id'=>1,'select_type'=>'SIMPLE','table'=>'think_user','partitions'=>NULL,'type'=>'sysSQL日志中會記錄每個SQL的執(zhí)行時間以及EXPLAIN分析結(jié)果,框架只是記錄分析結(jié)果,至于如何查出問題和解決則需要你具備一定的SQL性當(dāng)EXPLAIN分析結(jié)果中的extra中使用了filesort或者temporary的話,系統(tǒng)會額外記錄一個警告錯誤告訴我們某條SQL存在性合理使?查詢緩存盡量減少每次請求的查詢次數(shù),并對實時性要求不高的數(shù)據(jù)查詢合理規(guī)劃數(shù)據(jù)查詢緩存(優(yōu)先考慮使用Redis緩存)。Blog::where('id',10)->cache(30)->find();如果使用了關(guān)聯(lián)查詢,cache方法只能用于主模型的數(shù)據(jù)緩存,但你可以使用Cache類的remember方法進(jìn)行方便的數(shù)據(jù)緩存。$users=Cache::remember('users',function(){returnUser::with('profile')->where('status',1)->select();},30);不要過于糾結(jié)查詢次數(shù)盡量減少查詢次數(shù)是出于性能考慮,但不是必須,使用最少的查詢不代表性能就一定是最高。一個復(fù)雜的JOIN查詢性能不見得有兩次簡單的正確使?模型關(guān)聯(lián)不要總是以為模型的性能一定比Db類低,框架的ORM查詢設(shè)計經(jīng)過了較為合理的優(yōu)化,正確使用模型一樣可以有出色的性能,而且比Db查尤其是對于一些復(fù)雜的設(shè)計來說使用模型關(guān)聯(lián)顯得比直接用Db更加簡單,例如使用關(guān)聯(lián)預(yù)載入查詢就可以避免N+1查詢問題。User::with(['profile','book'])->select();如果用Db類自己實現(xiàn)的話,費(fèi)時費(fèi)力,性能還不一定優(yōu)。對于大量數(shù)據(jù)的處理操作,使用chunk分批處理方法。User::chunk(100,function($users){foreach($usersas$user){//處理數(shù)據(jù)}});對于內(nèi)存開銷比較大的應(yīng)用,在做大量數(shù)據(jù)查詢和處理的時候,使用cursor方法,可以利用PHP的生成器特性,減少內(nèi)存占用。$cursor=User::cursor();foreach($cursoras$user){//處理數(shù)據(jù)}你會發(fā)現(xiàn)用戶數(shù)據(jù)不論是1萬還是10萬級別,內(nèi)存開銷并沒有大的變化。涉及到對大量數(shù)據(jù)的處理,包括數(shù)據(jù)遷移、批量更新,盡量使用命令行指令運(yùn)行,否則會因為超時而中斷。善?數(shù)據(jù)集?法避免多次查詢可以通過數(shù)據(jù)集的方法完成的子集或者排序操作不要再次查詢,例如://模型查詢返回數(shù)據(jù)集對象$users=User::select();//按照用戶的成績由高到低排序$list1=$users->order('score','desc');//篩選成績在90分以上的用戶$list2=$users->where('score','>=',90);字段緩存利用下面指令在部署后生成字段緩存,可以減少每次數(shù)據(jù)表的字段查詢開銷。phpthinkoptimize:schema注意:一旦數(shù)據(jù)庫的表結(jié)構(gòu)發(fā)生變化,必須重新生成。ThinkPHP開發(fā)指北(三)安全篇在部署、開發(fā)等方面做了安全規(guī)范的全面指引安全問題不容忽視,而且一定要提前做好安全防范,而不是說項目完成后才需要關(guān)注安全問題,本篇在部署、開發(fā)等方面做了安全規(guī)范的全面指引,但除此外還需要注意業(yè)務(wù)邏輯的安全設(shè)計和服務(wù)器安全,才能讓你的項目更安全無虞。記得關(guān)注\h官網(wǎng)和微信公眾號,及時獲取官方的安全更新通告。規(guī)范部署?錄這一點很多開發(fā)者不是特別重視,安全是一個整體性的問題,任何一個環(huán)節(jié)出問題,帶來的后果都是一樣的嚴(yán)重,部署的安全策略是一個基礎(chǔ)安全問題。很多開發(fā)者往往不按照官方的部署規(guī)范進(jìn)行部署,請務(wù)必把你的WEB根目錄指向public目錄而不是應(yīng)用根目錄,并且不要隨意更改入口文件的位置。public目錄下面不要放除了入口文件和資源文件以外的其它應(yīng)用文件。禁?危險函數(shù)在PHP中禁用危險的函數(shù)可以減少安全風(fēng)險,特別是那些可能允許執(zhí)行任意代碼、文件包含或數(shù)據(jù)泄露的函數(shù)。以下是一些常見的應(yīng)該謹(jǐn)慎使用或禁用的PHP函數(shù):eval():執(zhí)行字符串作為PHP代碼,這可能導(dǎo)致代碼注入攻擊。exec():執(zhí)行一個命令行命令,可能被用于命令注入攻擊。shell_exec():執(zhí)行命令通過shell并返回完整的輸出作為字符串,同樣可能被用于命令注入。system():執(zhí)行一個命令并通過最后一個參數(shù)輸出執(zhí)行結(jié)果,也存在命令注入的風(fēng)險。passthru():執(zhí)行一個命令并傳遞原始輸出直接到瀏覽器,可能被用于執(zhí)行惡意命令。禁用危險函數(shù)可以幫助你避免一些未知的漏洞所造成的影響,確保數(shù)據(jù)安全。關(guān)閉調(diào)試模式在部署到生產(chǎn)環(huán)境的時候,確保你已經(jīng)關(guān)閉了調(diào)試模式,可以通過修改環(huán)境變量的方式關(guān)閉調(diào)試模式。\hThinkPHP知識庫無論是本地開發(fā)還是生產(chǎn)環(huán)境部署,都不建議直接通過修改配置文件的方式開啟/關(guān)閉調(diào)試模式,而應(yīng)該使用環(huán)境變量(本地開發(fā)可以通過定義.env文件)。關(guān)閉調(diào)試模式后,系統(tǒng)的健康狀態(tài)和運(yùn)行監(jiān)控主要依靠日志或者你使用的監(jiān)控服務(wù)。所以,要養(yǎng)成定時檢查日志和運(yùn)行狀態(tài)的習(xí)慣。使?強(qiáng)類型條件允許,盡量使用PHP8.2+版本,并在代碼中使用類型約束(類型安全),利遠(yuǎn)大于弊:能提高代碼可讀性PHP內(nèi)部對類型聲明的優(yōu)化可以減少類型判斷的開銷,從而提高代碼執(zhí)行效率?,F(xiàn)代IDE可以利用類型聲明提供更好的代碼自動完成、跳轉(zhuǎn)定義和重構(gòu)支持。避免PHP類型轉(zhuǎn)換帶來的隱患問題。簡化調(diào)試過程,快速定位問題。使用反射API來檢查和操作類型信息,為元編程提供了更多可能性請求變量過濾永遠(yuǎn)不要相信用戶的輸入,這是一句至理名言。盡可能的過濾請求變量能有效防范大部分的漏洞和隱患??蚣芙ㄗh的獲取請求變量的方法是Request類的param方法(如非必要不要再使用get或者post方法獲取,更不要使用原生的$_GET/$_POST等方法獲?。ublicfunctionindex(Request$request){$name=$request->param('name');//在這里可以根據(jù)你的業(yè)務(wù)需求進(jìn)行更嚴(yán)謹(jǐn)?shù)倪^濾//例如$name=$request->param('name','','htmlentities,strtolower');//或者使用驗證器進(jìn)行專門的驗證}對于有明確類型的請求變量,可以在使用param方法的時候使用類型強(qiáng)制轉(zhuǎn)換,例如:\hThinkPHP知識庫//強(qiáng)制轉(zhuǎn)換字符串?dāng)?shù)據(jù)$name=$request->param('name/s');//強(qiáng)制轉(zhuǎn)換整型數(shù)據(jù)$name=$request->param('id/d');//強(qiáng)制轉(zhuǎn)換浮點型數(shù)據(jù)$name=$request->param('score/f');}或者直接使用方法參數(shù)獲取請求變量publicfunctionindex(string$name){//在這里可以根據(jù)你的業(yè)務(wù)需求進(jìn)行更嚴(yán)謹(jǐn)?shù)倪^濾//或者使用驗證器進(jìn)行專門的驗證}如果你需要對所有數(shù)據(jù)進(jìn)行處理,可以設(shè)置全局的過濾方法。對不同的應(yīng)用需求設(shè)置default_filter過濾規(guī)則(默認(rèn)沒有任何過濾規(guī)則),常見的安全過濾函數(shù)包括stripslashes、htmlentities、htmlspecialchars和strip_tags等,請根據(jù)業(yè)務(wù)場景選擇最合適的過濾方法。如果需要獲取多個數(shù)據(jù),建議使用only方法指定需要獲取的變量名稱,避免有些不懷好意的數(shù)據(jù)提交導(dǎo)致權(quán)限問題。publicfunctionindex(Request$request){//指定表單數(shù)據(jù)名稱$data=$request->only(['name','title']);}當(dāng)你使用數(shù)據(jù)庫或者模型操作寫入數(shù)據(jù)的時候,也可以指定字段,避免非法和不希望的字段寫入數(shù)據(jù)庫。//模型User::allowField(['name','title'])\hThinkPHP知識庫//數(shù)據(jù)庫Db::name('user')->field(['name','title'])->insert($data);模型還有一個只讀字段功能能避免你的數(shù)據(jù)受到外部的修改。上傳檢測網(wǎng)站的上傳功能也是一個非常容易被攻擊的入口,所以對上傳功能的安全檢查是尤其必要的。系統(tǒng)的驗證類提供了文件上傳的安全支持,包括對文件后綴、文件類型、文件大小以及上傳圖片文件的合法性檢查,確保你已經(jīng)在上傳操作中啟用了這些合法性檢查。將上傳的文件存儲在安全的路徑中,避免直接訪問敏感文件,并禁用執(zhí)行權(quán)限。建議將文件保存在非Web根目錄下,并通過URL訪問或通過權(quán)限控制保護(hù)文件訪問。SQL注入ThinkPHP的查詢統(tǒng)一使用了PDO的prepare預(yù)查詢和參數(shù)綁定機(jī)制,能有效的避免SQL注入的發(fā)生。但不代表絕對安全,如果你缺乏良好的代碼規(guī)范,尤其是使用了原生查詢的情況下仍然有可能被利用。一個最簡單的原則就是不要讓用戶決定你的查詢條件(或者字段排序)和控制你的查詢數(shù)據(jù)。對于一些字符串的查詢條件(包括原生查詢)或者特殊的查詢(包括ORDER部分),需要手動進(jìn)行參數(shù)綁定。//錯誤的Db::query("select*fromthink_userwhereid=$idANDstatus=$statis");//正確的Db::query("select*fromthink_userwhereid=?ANDstatus=?",[$id,$status]);//正確的Db::execute("updatethink_usersetname=:namewherestatus=:status",['name''status']);
=>'thinkphp',=>1\hThinkPHP知識庫Db::name('user')->whereRaw('id>?ANDstatus=?',[10,1])->select();使?驗證器對于大量的表單需要驗證的情況,建議使用驗證器功能統(tǒng)一進(jìn)行數(shù)據(jù)的合規(guī)驗證。驗證器的驗證操作應(yīng)該在控制器或者路由階段使用validate方法進(jìn)行處理,模型的數(shù)據(jù)驗證功能新版已經(jīng)取消不再建議使用,模型和數(shù)據(jù)庫操作的時候應(yīng)該傳入經(jīng)過安全處理過的數(shù)據(jù)。XSS攻擊跨站腳本攻擊(cross-sitescripting,簡稱XSS),XSS是一種在web應(yīng)用中的計算機(jī)安全漏洞,它允許惡意web用戶將代碼植入到提供給其它用戶使用的頁面中。在渲染輸出的頁面中,要對一些數(shù)據(jù)進(jìn)行安全處理,防止被惡意利用造成XSS攻擊,ThinkPHP新版本對所有的輸出都已經(jīng)經(jīng)過了htmlentities轉(zhuǎn)義輸出,確保安全。如果你的環(huán)境要求你使用Markdown而不是HTML,那就不要使用HTML了。CSRF攻擊CSRF跨站請求偽造是Web應(yīng)用中最常見的安全威脅之一,攻擊者偽造目標(biāo)用戶的HTTP請求,然后此請求發(fā)送到有CSRF漏洞的網(wǎng)站,網(wǎng)站執(zhí)行此請求后,引發(fā)跨站請求偽造攻擊。攻擊者利用隱蔽的HTTP連接,讓目標(biāo)用戶在不注意的情況下單擊這個鏈接,由于是用戶自己點擊的,而他又是合法用戶擁有合法權(quán)限,所以目標(biāo)用戶能夠在網(wǎng)站內(nèi)執(zhí)行特定的HTTP鏈接,從而達(dá)到攻擊者的目的。首先必須啟用HTTPS,這是前提,雖然本身HTTPS并不能防止CSRF。開啟表單令牌驗證,盡量開啟強(qiáng)制路由并嚴(yán)格規(guī)范每個URL請求,定義單獨(dú)的MISS路由規(guī)則。遵循請求類型的使用規(guī)范并做好權(quán)限驗證,刪除操作必須使用DELETE請求,數(shù)據(jù)更改操作必須使用POST、PUT或者PATCH請求方法,GET請求不應(yīng)該更改任何數(shù)據(jù)。設(shè)置Cookie的httponly和SameSite參數(shù),"SameSite"是一個用于HTTP響應(yīng)頭中的Set-Cookie屬性,用來控制cookie的跨站請求。這個屬性可以設(shè)置為以下三個值之一:1.Lax:這是默認(rèn)值,表示cookie僅在非跨站請求和頂級導(dǎo)航中發(fā)送。\hThinkPHP知識庫3.None:表示cookie可以跨站發(fā)送,但要求必須使用安全傳輸協(xié)議(HTTPS)。設(shè)置SameSite=strict這可以提高網(wǎng)站的安全性,防止跨站請求偽造(CSRF)攻擊。會話劫持會話劫持是指攻擊者利用各種手段來獲取目標(biāo)用戶的sessionid。一旦獲取到sessionid,那么攻擊者可以利用目標(biāo)用戶的身份來登錄網(wǎng)站,獲取目標(biāo)用戶的操作權(quán)限。有效的防護(hù)策略包括:在每次會話啟動的時候,調(diào)用regenerate方法。Session::start();Session::regenerate(true);更改session配置參數(shù),開啟安全選項:'use_trans_sid''httponly''secure'
=>0,=>true,=>true,反序列化和PHP對象注入如果你將不可信的數(shù)據(jù)傳遞給unserialize(),則通常是這兩個結(jié)果之一:PHP對象注入,它能用于
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 包裝設(shè)計師安全技能知識考核試卷含答案
- 炭素配料工保密意識水平考核試卷含答案
- 啤酒花加工工安全宣傳測試考核試卷含答案
- 金融風(fēng)險管理師標(biāo)準(zhǔn)化測試考核試卷含答案
- 醫(yī)療護(hù)理員道德水平考核試卷含答案
- 塑料編織工班組評比競賽考核試卷含答案
- 寶玉石鑒別工崗前紀(jì)律考核試卷含答案
- 插花花藝師安全實操能力考核試卷含答案
- 催化劑生產(chǎn)工崗前班組建設(shè)考核試卷含答案
- 電線電纜制造工改進(jìn)考核試卷含答案
- 甲狀腺功能亢進(jìn)危象課件
- 介入護(hù)士進(jìn)修總結(jié)匯報
- 電網(wǎng)工程勞務(wù)分包投標(biāo)方案(技術(shù)方案)
- 江蘇省沭陽縣修遠(yuǎn)中學(xué)2024-2025學(xué)年高一生物上學(xué)期第二次月考試題
- 婦產(chǎn)科年終總結(jié)
- 北京市各區(qū)縣街道鎮(zhèn)鄉(xiāng)村村名及行政區(qū)劃代碼
- 輸血科進(jìn)修匯報
- SMD-PFMEA模板中英文版
- 2024年山東醫(yī)藥工業(yè)設(shè)計院招考公開引進(jìn)高層次人才和急需緊缺人才筆試參考題庫(共500題)答案詳解版
- 中國歷史地理智慧樹知到期末考試答案章節(jié)答案2024年北京大學(xué)
- JC∕T 60016-2022 建筑用免拆復(fù)合保溫模板應(yīng)用技術(shù)規(guī)程
評論
0/150
提交評論