1. 程式人生 > >ThinkPHP5 Nginx下的配置——支援pathinfo訪問和隱藏入口檔案index.php的rewrite規則

ThinkPHP5 Nginx下的配置——支援pathinfo訪問和隱藏入口檔案index.php的rewrite規則

最近賦閒在家,看到TP都更新到5.0.6了,於是弄過來寫了個小專案熟悉了下,發現改動確實蠻大的。

首先就是支援Composer了。(強烈建議使用Composer安裝,因為TP5的一些驗證碼之類的擴充套件包必須要用到Composer來安裝。)
檔案命名規範的改變:控制器類檔名“UserController.class.php”不再需要“Controller.class”這一堆,直接User.php這樣命名,很清爽;
捨棄了之前讓TP背了不少罵名的單字母函式:I、U、M、C等;
一些資料庫的操作方法也有改動:如save() 改為 update(); getField() => column(); add() => insert()(insert()方法預設返回新增的條數,要返回主鍵的話使用insertGetId())等等;
還有目錄結構也有很大的調整,比如第三方類庫目錄調整為/vendor/下,入口檔案也由根目錄修改到/public/下面;
還有配置檔案,路由和資料庫的配置也獨立出來了。
總之,跟之前的3.x相比完全是兩回事了,很多地方感覺有點向laravel靠攏了^_^

我在部署的時候也遇到了些問題,因為伺服器從用TP起都是用apache,這次特意換回nginx的,但是由於官方手冊的nginx配置寫的並不詳細,在配置偽靜態和pathinfo的時候也查了不少相關資料。

url裡public目錄的隱藏

其實正常思路的話這個url裡的public本身就是不存在的,然後呢,其實也不叫隱藏public目錄,這裡只是考慮到有些童鞋可能還會按之前3.x時代的習慣來配置網站根目錄,我們來糾個可能會出現的錯。
出於安全的考慮,TP5的入口檔案改成放在public下了,因為這樣的話能防止被惡意使用者訪問到“/thinkphp/”、“/vendor/”等等這些目錄下的檔案。所以當你以之前的習慣將網站documentroot配置為專案根目錄的時候就會需要在url後面加上/public/來訪問。當然可能也會有童鞋把入口檔案放回到根目錄下,然後還是以之前3.x版那樣的形式訪問了。
但是很顯然,這麼做並不是那麼的科學。
假設專案目錄為“/web/wwwroot/augsky.com”,那麼我們在網站的nginx配置檔案裡面將root配置為:

root  /web/wwwroot/augsky.com/public;

但是一定要記得將open_basedir設定為上一級專案的根目錄下,不然應用會沒有許可權呼叫除public目錄下的其他檔案,網站會報500無法訪問。(open_basedir的配置預設在php.ini裡面,但如果是多個虛擬機器環境的話有可能會在各個網站的user.ini檔案裡,這個要根據自己的實際情況來。)具體配置如下:
open_basedir=/web/wwwroot/augsky.com:/tmp/:/proc/

隱藏入口檔案index.php:

location /  {                    
    try_files $uri $uri/ /index.php?s=$uri&$args;                     
    #如果請求不是檔案或目錄,則將uri交給index.php處理,同時保留引數          
}

說一下try_files:

try_files 
語法: try_files file1 [file2 ... filen] uri                     
        OR         
     try_files file1 [file2 ... filen] =code 
預設值: 無 
作用域: server location
try_files支援多個引數,每個引數代表一個檔案,系統將按順序檢查這些檔案是否存在,存在就直接執行,斜線“/”結尾代表目錄,若都不存在,則會重定向到最後一個引數指向的檔案或者返回指定的http狀態碼。

pathinfo配置

在配置檔案裡面增加這一段(如果你是lnmp一鍵包使用者,請略過這一段往下翻):

location ~ [^/]\.php(/|$) {             
    set $path_info "";          
    #定義變數 $real_script_name,用於存放真實地址             
    set $real_script_name $fastcgi_script_name;             
    #如果地址與引號內的正則表示式匹配             
    if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") {             
      #將檔案地址賦值給變數 $real_script_name             
      set $real_script_name $1;             
      #將檔案地址後的引數賦值給變數 $path_info             
      set $path_info $2;             
    }             
    #配置fastcgi的一些引數             
    fastcgi_pass  unix:/tmp/php-cgi.sock;             
    fastcgi_index index.php;             
    fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;             
    fastcgi_param SCRIPT_NAME $real_script_name;             
    fastcgi_param PATH_INFO $path_info;             
    include        fastcgi_params; 
}
上面需要說明的是fastcgi_pass的設定,這個得根據你實際的php版本和安裝目錄來設定。
好,做完這些之後,儲存,重啟nginx和php就能生效了。如果你是lnmp一鍵包使用者的話不用上面這樣設定,往下面看:

lnmp一鍵包pathinfo的設定

其實lnmp一鍵包裡面的pathinfo軍哥已經都寫好了,我們只需要把include enable-php.conf;修改成include enable-php-pathinfo.conf;然後重啟lnmp就搞定了。

#include enable-php.conf;或者,你直接註釋掉這一行,在下面新增新的一行 
include enable-php-pathinfo.conf;
就是這樣簡單。下面順便附上在url裡隱藏模組的方法

url隱藏預設模組index

很簡單,在入口檔案裡面定義常量BIND_MODULE為你使用的模組就好了,以預設的index為例:

define('BIND_MODULE','index');

這樣,在url裡面不會在有模組名這一級目錄了。要知道,層級少一些的url對SEO是有好處的。
下面是nginx裡面location的匹配規則,摘自
Nginx location的匹配規則

~ 波浪線表示執行一個正則匹配,區分大小寫
~* 表示執行一個正則匹配,不區分大小寫
^~ ^~表示普通字元匹配,如果該選項匹配,只匹配該選項,不匹配別的選項,一般用來匹配目錄
= 進行普通字元精確匹配
@ #"@" 定義一個命名的 location,使用在內部定向時,例如 error_page, try_files

location 匹配優先順序

= 精確匹配會第一個被處理。如果發現精確匹配,nginx停止搜尋其他匹配。
普通字元匹配,正則表示式規則和長的塊規則將被優先和查詢匹配,也就是說如果該項匹配還需去看有沒有正則表示式匹配和更長的匹配。
^~ 則只匹配該規則,nginx停止搜尋其他匹配,否則nginx會繼續處理其他location指令。
最後匹配理帶有"~"和"~*"的指令,如果找到相應的匹配,則nginx停止搜尋其他匹配;當沒有正則表示式或者沒有正則表示式被匹配的情況下,那麼匹配程度最高的逐字匹配指令會被使用。