本章對于新手來說很重要,能基本理解本章的所有知識,對于后面的學習很有幫助。俗話說“基礎不牢,地動山搖”。
## 目錄結構
下載**ThinkPHP3.2.3**完整版后,解壓到www目錄。我們可以看到以下目錄結構
├── Application
├── Public
├── README.md
├── ThinkPHP
│?? ├── Common
│?? ├── Conf
│?? ├── LICENSE.txt
│?? ├── Lang
│?? ├── Library
│?? │?? ├── Behavior
│?? │?? ├── Org
│?? │?? ├── Think
│?? │?? └── Vendor
│?? ├── Mode
│?? │?? ├── Api
│?? │?? ├── Sae
│?? │?? ├── api.php
│?? │?? ├── common.php
│?? │?? └── sae.php
│?? ├── ThinkPHP.php
│?? ├── Tpl
│?? └── logo.png
├── composer.json
└── index.php
一個應用的目錄是這樣的:
www WEB部署目錄(或者子目錄)
├─index.php 入口文件
├─composer.json composer 依賴關系文件
├─README.md README文件
├─Application 應用目錄
├─Public 資源文件目錄
└─ThinkPHP 框架目錄
ThinkPHP框架目錄結構如下:
├─ThinkPHP 框架系統目錄(可以部署在非web目錄下面)
│ ├─Common 核心公共函數目錄
│ ├─Conf 核心配置目錄
│ ├─Lang 核心語言包目錄
│ ├─Library 框架類庫目錄
│ │ ├─Think 核心Think類庫包目錄
│ │ ├─Behavior 行為類庫目錄
│ │ ├─Org Org類庫包目錄
│ │ ├─Vendor 第三方類庫目錄
│ │ ├─ ... 更多類庫目錄 比如**onethink**中的OT
│ ├─Mode 框架應用模式目錄
│ ├─Tpl 系統模板目錄
│ ├─LICENSE.txt 框架授權協議文件
│ ├─logo.png 框架LOGO文件
│ ├─README.txt 框架README文件
│ └─index.php 框架入口文件
當然應用目錄不一定是Application,也可以是app,或者是入口文件所在目錄。看一下示列代碼中的startup:
examples
└── startup
├── Common 公共函數庫
├── Home 應用目錄
├── Runtime
└── index.php
└─ThinkPHP
這是因為我將startup里的入口文件index.php中的常量 **APP\_PATH** 定義為了當前目錄:
`define('APP_PATH','./');`
`require '../../ThinkPHP/ThinkPHP.php';`
startup中Common、Home、Runtime這幾個目錄都是自動生成的,我只是定義了下入口文件。這也印證了官方手冊里的話:
> README.md文件僅用于說明,實際部署的時候可以刪除。
> 上面的目錄結構和名稱是可以改變的,這取決于你的入口文件和配置參數。 Application目錄默認是空的,但是第一次訪問入口文件會自動生成,參考后面的入口文件部分。
目錄結構還要注意安全
> 在實際部署應用的時候,我們建議除了應用入口文件和Public資源目錄外,其他文件都放到非WEB目錄下面,具有更好的安全性。
> 實際上通過修改一些常量,可以將ThinkPHP框架目錄和應用目錄的結構修改的面目全非,這樣別人拿到源碼,第一眼認不出來ThinkPHP,偽裝的目的也就達到了。
## 什么是控制器,如何建立
稍微懂點PHP的童鞋都知道M(模型)V(視圖)C(控制器)。
控制器是我們處理響應的第二層,在其中根據用戶過來的url,去進行業務數據調度和決定視圖呈現的場所。
它物理上來說是一個類文件。
首先,我們找到startup下的默認控制器 就是 `examples/startup/Home/Controller/IndexController.class.php`文件。
**IndexController?** 是控制器類名,由 **控制器名(駝峰法,首字母大寫)**的Index + Controller組成、
控制器文件的命名方式是:類名+class.php(類文件后綴)
我們訪問 域名/[目錄名(如果示列目錄Apache配置了域名的話,此處不需要,localhost域名需要帶上路徑目錄名如yang\_book_)]/examples/startup時的效果如下:

后面我講的演示url路徑會自動省略`.../examples/` 直接startup等目錄開頭,你們使用時要能自動轉換一下訪問路徑。
**$this-\>show()** 我們后面基礎知識部分的控制器章節會講到。
我們看下控制器類,IndexController控制器類的開頭是命名空間定義:
`namespace Home\Controller;`
這是系統的規范要求,表示當前類是Home模塊下的控制器類,命名空間和實際的控制器文件所在的路徑是一致的,也就是說:Home\Controller\IndexController類 對應的控制器文件位于應用目錄下面的 Home/Controller/IndexController.class.php,如果你改變了當前的模塊名,那么這個控制器類的命名空間也需要隨之修改。
> 注意:命名空間定義必須寫在所有的PHP代碼之前聲明,否則會出錯
`use Think\Controller;`
表示引入 ThinkController 命名空間便于直接使用。 所以,
`use Think\Controller;`
`class IndexController extends Controller`
等同于使用:
`class IndexController extends \Think\Controller`
對于**3.1**的用戶而言,如果你習慣了使用**Action**定義控制器的話,可以這樣定義:
`namespace Home\Action;`
`use Think\Action;`
`class IndexAction extends Action{`
`}`
然后,在配置文件中,設置:
`'DEFAULT_C_LAYER'=>'Action'`
上面的設置方式通常可以用于原有3.1項目的升級。
### 配置文件在哪兒?如何設置
首先我們知道ThinkPHP很靈活,這歸功于他提供了很多配置項,供大家重新配置。
配置文件分應用配置和框架配置。
應用配置又分公共配置和模塊配置:
- startup/Common/Conf/config.php 公共配置
- startup/Home/Conf/config.php 模塊配置
框架配置位于 /ThinkPHP/conf 下
默認有兩個 convention.php和debug.php 我們一般稱為慣例配置和調試配置。
當然還有其他配置項,因此有下面的一個優先級大家要了解下:
慣例配置-\>應用配置-\>模式配置-\>調試配置-\>狀態配置-\>模塊配置-\>擴展配置-\>動態配置
設置配置的方法有兩種,一種是靜態設置,一種是動態設置。
靜態設置指的是在公共配置文件中寫入框架配置中存在的鍵名(不存在的是自定義配置),覆蓋框架默認配置。 這樣的好處是,寫一處,全局被影響。
動態設置指的是在代碼中,通常是控制器和模型中,用C('鍵名','值')的方式進行臨時性修改,影響范圍小,只會在一次請求期間經過的代碼中起作用。
## 如何開啟調試模式
首先,調試模式只的是在開發階段應用對應的框架模式。該模式下和正式部署環境的時候有一些區別:
- 不會在Runtime目錄下面生成**common~runtime.php**文件(應用編譯緩存文件)。
- 會自動加載框架的調試配置文件(位于`ThinkPHP/Conf/debug.php`)和應用調試配置文件(位于`Application/Common/Conf/debug.php`)
- 異常時顯示具體的錯誤信息,如果在部署模式下面,你可能看到的是一個簡單的提示文字,例如:

- 記錄日志,部署模式不記錄日志,且**SQL**級別日志只在調試模式時記錄。
- 在部署模式下面,頁面Trace顯示的調試信息沒有調試模式完整,通常我們建議頁面Trace配合調試模式一起使用。
- Mongo數據庫驅動由于接口的特殊性,不存在執行SQL的概念,因此SQL日志記錄功能是額外封裝實現的,所以出于性能考慮,只有在開啟調試模式的時候才支持使用getLastSql方法獲取最后執行的SQL記錄。
- 開啟錯誤信息顯示,默認是關閉的。
鑒于以上幾點,我們應該在開發的時候盡量開啟調試模式,部署時關閉調試模式。
> 系統的默認情況下,調試模式是開啟錯誤信息顯示的,部署模式則關閉錯誤信息顯示。
開啟的方法很簡單,入口文件 index.php 添加一行:
~~~
define('APP_DEBUG', 1);
~~~
調試模式開啟的相關配置,進階知識里會講到。
## 如何使用模板標簽
模板標簽是TP模板的重要組成部分,有了它,我們才能擺脫html+PHP混編時那種混亂的\<?php ?\> 使我們的模板看上去簡潔、優雅。
變量輸出使用普通標簽就足夠了,但是要完成其他的控制、循環和判斷功能,就需要借助模板引擎的標簽庫功能了,系統內置標簽庫的所有標簽無需引入標簽庫即可直接使用。
標簽和HTML標簽一樣 分為 閉合標簽和不閉合標簽。比如 :
- `<assign name="var" value="123" />`
- `<volist name="list" id="vo">`
`{$vo.id}:{$vo.name}<br/>`
`</volist>`
標簽的使用一般都是 **<標簽名 屬性參數="">包裹內容</標簽名>** 或者**<標簽名 屬性參數="" />**
`<else/>` 標簽不能單獨使用,必須在比較標簽如 eq、if中間使用。
訪問 **startup/Index/tags** ,會見到以下輸出:

我們先看一下Index控制器下tags方法的內容:
public function tags()
$this->assign('age',10);
$this->assign('likes', array('爸爸', '媽媽', '小紅'));
$this->assign('money', 0);
$this->display();
}
我們看一下`/Home/view/Index/tags.html`的內容。
~~~
<p>我今年{$age}歲了。</p>
<p>我是一個<eq name="age" value="18">大人<else/>小孩</eq>。</p>
<volist name="likes" id="like">
<p>我喜歡{$like}。</p>
</volist>
<p><empty name="money">我沒有一分錢,很窮。</empty></p>
<include file="Index/award" />
~~~
大概常用的標簽都用到了,比較標簽、include、循環標簽。
## 項目函數文件在哪兒,如何定義自己的函數
目錄結構已經講了公用函數目錄。項目函數文件路徑是`/Home/Common/function.php` 和Common公共目錄一樣也是在一個Common下的function.php。TP的設計就是讓我們少記憶一些結構。
定義函數很簡單,只要在其中寫自己的函數就行了。
比如我在 項目函數中定義了hello function :
function hello()
echo 'hello!';
}
然后 我的Index下custom_function 方法中使用了 hello()
訪問 `startup/Index/custom_function` 然后就能看見自定義函數起作用了:

### 如何隱藏入口
每次我們默認的url 里 必須帶上**index.php** 這樣看上去長又丑陋。
如果想偽靜態化,顯示個**index.php** 就失效了。
所以我們想隱藏**index.php**。
只需要Apache開啟rewrite模塊,和項目和Index.php的目錄放入一個.htaccess文件即可。
可以通過URL重寫隱藏應用的入口文件index.php,下面是相關服務器的配置參考:
[ Apache ]
- httpd.conf配置文件中加載了**mod\_rewrite.so**模塊
- AllowOverride None 將None改為 All
- 把下面的內容保存為.htaccess文件放到應用入口文件的同級目錄下
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>
[ IIS ]
如果你的服務器環境支持**ISAPI_Rewrite**的話,可以配置**httpd.ini**文件,添加下面的內容:
`RewriteRule (.*)$ /index.php?s=$1 [I]`
在IIS的高版本下面可以配置web.Config,在中間添加rewrite節點:
<rewrite>
<rules>
<rule name="OrgPage" stopProcessing="true">
<match url="^(.*)$" />
<conditions logicalGrouping="MatchAll">
<add input="{HTTP_HOST}" pattern="^(.*)$" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="index.php/{R:1}" />
</rule>
</rules>
</rewrite>
[ Nginx ]
在Nginx低版本中,是不支持**PATHINFO**的,但是可以通過在Nginx.conf中配置轉發規則實現:
location / {
// …..省略部分代碼
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=$1 last;
break;
}
}
其實內部是轉發到了ThinkPHP提供的兼容模式的URL,利用這種方式,可以解決其他不支持PATHINFO的WEB服務器環境。
如果你的ThinkPHP安裝在二級目錄,Nginx的偽靜態方法設置如下,其中youdomain是所在的目錄名稱。
location /youdomain/ {
if (!-e $request_filename){
rewrite ^/youdomain/(.*)$ /youdomain/index.php?s=$1 last;
}
}
原來的訪問URL:
`http://serverName/index.php/模塊/控制器/操作/[參數名/參數值...]`
設置后,我們可以采用下面的方式訪問:
`http://serverName/模塊/控制器/操作/[參數名/參數值...]`
默認情況下,URL地址中的模塊不能省略,如果你需要簡化某個模塊的URL訪問地址,可以通過設置模塊列表和默認模塊或者采用子域名部署到模塊的方式解決,請參考后面的模塊和域名部署部分。
- 序
- 前言
- 內容簡介
- 目錄
- 基礎知識
- 起步
- 控制器
- 模型
- 模板
- 命名空間
- 進階知識
- 路由
- 配置
- 緩存
- 權限
- 擴展
- 國際化
- 安全
- 單元測試
- 拿來主義
- 調試方法
- 調試的步驟
- 調試工具
- 顯示trace信息
- 開啟調試和關閉調試的區別
- netbeans+xdebug
- Socketlog
- PHP常見錯誤
- 小黃鴨調試法,每個程序員都要知道的
- 應用場景
- 第三方登錄
- 圖片處理
- 博客
- SAE
- REST實踐
- Cli
- ajax分頁
- barcode條形碼
- excel
- 發郵件
- 漢字轉全拼和首字母,支持帶聲調
- 中文分詞
- 瀏覽器useragent解析
- freelog項目實戰
- 需求分析
- 數據庫設計
- 編碼實踐
- 前端實現
- rest接口
- 文章發布
- 文件上傳
- 視頻播放
- 音樂播放
- 圖片幻燈片展示
- 注冊和登錄
- 個人資料更新
- 第三方登錄的使用
- 后臺
- 微信的開發
- 首頁及個人主頁
- 列表
- 歸檔
- 搜索
- 分頁
- 總結經驗
- 自我提升
- 進行小項目的鍛煉
- 對現有輪子的重構和移植
- 寫技術博客
- 制作視頻教程
- 學習PHP的知識和新特性
- 和同行直接溝通、交流
- 學好英語,走向國際
- 如何參與
- 瀏覽官網和極思維還有看云
- 回答ThinkPHP新手的問題
- 嘗試發現ThinkPHP的bug,告訴官方人員或者push request
- 開發能提高效率的ThinkPHP工具
- 嘗試翻譯官方文檔
- 幫新手入門
- 創造基于ThinkPHP的產品,進行連帶推廣
- 展望未來
- OneThink
- ThinkPHP4
- 附錄