解压后在浏览器中访问页面(目录),然后更改./Application/Home/Controller/IndexController.class.php
中IndexController -> index()
中的内容,即可更改欢迎页面。
./
├─Application/ 应用目录(模块集合)
│ ├─*/ (除了 Runtime 外的其他目录)模块
│ │ ├─Common/ 模块函数库
│ │ ├─Conf/ 模块配置
│ │ ├─Controller/ 控制器
│ │ ├─Model/ 模型
│ │ ├─View/ 视图
│ │ └─Conf/ 惯例配置
│ ├─Common/ 通用模块(不可以直接访问,优先于其他模块执行,内部结构见上)
│ ├─Home/ 系统自动生成的模块(内部结构见上)
│ └─Runtime 缓存目录
├─Public/ 公共资源目录(存放所有的静态资源,如样式表脚本、图片、字体)
├─ThinkPHP/ 核心框架目录
│ ├─Common/ 通用函数库
│ ├─Conf/ 惯例配置
│ ├─Lang/ 语言包
│ ├─Library/ 类库
│ ├─Mode/ 应用模式
│ ├─Tpl/ 框架自带模板
│ └─ThinkPHP.php 框架入口文件(公共入口文件)
└─index.php 应用入口(应用对外提供的接口,所有请求都从这个开始(所以 ThinkPHP 可以是单入口的)引入了公共入口文件)
./Application/
下新建目录./index.php
)中定义:define('BIND_MODULE', 'mod');
再打开框架的页面,系统会自动在 ./Application/
下生成名为 mod
的模块。更改 ./Application/mod/Controller/IndexController.class.php
中 IndexController -> index()
中的内容,即可更改对应的页面。在入口文件中绑定模块后,默认访问的就是这个模块。dump($var)
优点:将业务逻辑、视图展示和数据处理分离开,降低设计、管理的难度,代码也更具结构性,更容易维护、重用。(合理分工带来的效率提升)
用户
↕
C(服务员)
↕ ↕
M(厨师)↔ V(摆盘)
↕
DB(仓库)
./ThinkPHP/Conf/convention.php
)./Application/Common/Conf/config.php
)./ThinkPHP/Conf/debug.php
)./Application/*/Conf/config.php
)采用合并覆盖机制,因此优先级从后到前。
通过在入口文件(./index.php
)定义 CONF_EXT
常量指定格式。配置的格式不影响框架的惯例配置,只对模块配置产生影响。
# ./Application/Home/Conf/config.yaml
YAML : yaml
// ./index.php
//...
define('CONF_EXT', '.yaml');
//...
// ./Application/Home/Controller/IndexController.class.php
// ...
public function index(){
$config = C('');
dump($config);
// ...
// 输出中可以找到
['YAML'] => string(4) 'yaml'
通过 C
函数读取配置:
读取全部配置项:
C('')
读取配置项名称为 name
的配置项:
C('name')
读取配置项名称为 name
的配置项,如未配置则返回 default
:
C('name', null, 'default')
读取二维数组配置,父子项之间以点号连接:
C('parent.sub')
配置名称不区分大小写,但在二维数组配置读取的参数中,parent
严格区分大小写。
通过 C
函数进行动态配置,以在程序逻辑中临时改变配置。
设置配置项名称为 name
的配置项:
C('name', $val)
批量配置:
C($conf_array)
$conf_array
中键为配置项名称,值为配置值。
通过设置 LOAD_EXT_CONFIG
配置项的值来加载当前模块的自定义配置文件,如:
// ./Application/Home/Conf/user.php
return array(
'USER_NAME' => 'haha'
);
// ./Application/Home/Conf/upload.php
return array(
'UPLOAD_NAME' => 'gaga'
);
// ./Application/Home/Conf/config.php
return array(
'LOAD_EXT_CONFIG' => 'user,upload'
);
// ./Application/Home/Controller/IndexController.class.php
// ...
public function index(){
$config = C('');
dump($config);
// ...
// 输出中可以找到
['USER_NAME'] => string(4) 'haha'
['UPLOAD_NAME'] => string(4) 'gaga'
Controller
;类名以大写开头的驼峰命名法命名。public
修饰的方法是操作方法,可从外部访问;以 protected
或 private
修饰的不能从外部访问;操作方法采用驼峰命名法命名。在执行某个操作方法之前 / 之后会自动调用的方法。
// ./Application/Home/Controller/IndexController.class.php
//...
class IndexController extends Controller { // 控制器
public function _before_index(){ //前置操作
echo "index.before<br>";
}
public function index(){ //操作方法
echo "index<br>";
}
public function _after_index(){ //前置操作
echo "index.after<br>";
}
}
// 浏览器访问./
index.before
index
index.after
通过配置 ACTION_SUFFIX
的值改变操作方法的书写形式。不影响网址的展现形式,只会对操作方法的定义产生影响。
// ./Application/Home/Controller/IndexController.class.php
//...
class IndexController extends Controller { // 控制器
public function index(){ //操作方法
echo "index<br>";
}
public function list(){ //保留字,打开./时会报错
echo "list";
}
}
//配置`ACTION_SUFFIX`的值改变操作方法的书写形式
// ./Application/Home/Conf/config.php
return array(
//...
'ACTION_SUFFIX' => 'Action'
);
// ./Application/Home/Controller/IndexController.class.php
//...
class IndexController extends Controller { // 控制器
public function index(){ //由于没有后缀,打开./时会报错
echo "index<br>";
}
public function listAction(){ //通过访问./index.php/Home/Index/List来执行
echo "list";
}
}
空控制器是当系统找不到请求的控制器名称时,系统会尝试定位到空的控制器 EmptyController
;
空操作是当系统找不到请求的操作方法时,系统会尝试定位到空的操作方法 _empty
。
利用这个机制可以实现错误页面和 URL 优化。
// ./Application/Home/Controller/EmptyController.class.php
<?php
namespace Home\Controller;
use Think\Controller;
class EmptyController extends Controller {
public function _empty(){
echo "not found";
}
}
//当访问不存在的页面(如 ./index.php/Home/User/index)时,会用 `EmptyController -> _empty()` 中的内容替换默认的错误页面
可以设置参数 ACTION_BIND_CLASS
来开启,可以让开发工作更加细化。此时,控制器和操作方法的定义成了目录的形式。
//配置`ACTION_SUFFIX`的值改变操作方法的书写形式
// ./Application/Home/Conf/config.php
return array(
//...
'ACTION_BIND_CLASS' => true
);
// 新建目录 ./Application/Home/Controller/Index
// ./Application/Home/Controller/Index/index.class.php
<?php
namespace Home\Controller\Index; //命名空间根据目录结构来
use Think\Controller;
class index extends Controller {
public function run(){
echo "bind action";
}
}
// 浏览器访问 ./
bind action
new
实例化A
函数R
函数通过 URL_MODEL
配置:
0
:普通模式(http://domain/index.php?m=model&c=controller&a=action
)1
:PathInfo(http://domain/index.php/model/controller/action
)(默认)2
:ReWrite(http://domain/model/controller/action
)3
:兼容模式PathInfo、ReWrite 需要运行环境支持。
U
函数ThinkPHP 提供U
函数动态生成模式匹配的 URL:
U('地址表达式', ['参数'], ['伪静态后缀'], ['显示域名'])
地址表达式
:[模块/控制器/操作#锚点@域名]?参数1=值1&参数2=值2...
URL_CASE_INSENSITIVE
实现不区分大小写的 URL 访问通常为了满足更好的 SEO 效果:
URL_HTML_SUFFIX
配置伪静态后缀URL_DENY_SUFFIX
配置禁止访问的URL后缀// ./Application/Home/Controller/IndexController.class.php
// 该部分为下面三个模式共用
//...
class IndexController extends Controller {
public function index(){
$this -> listActionsUrl();
}
private function listActionsUrl() {
echo '当前 URL 模式为:' . C('URL_MODEL'); . '<br>';
echo 'User 控制器 index 的操作方法的 URL 为:' . U('Home/User/index'); . '<br>';
echo 'User 控制器 edit 的操作方法的 URL 为:' . U('Home/User/edit'); . '<br>';
echo 'User 控制器 login 的操作方法的 URL 为:' . U('Home/User/login'); . '<br>';
}
}
// ./Application/Home/Controller/UserController.class.php
//...
class UserController extends Controller {
public function index(){
echo 'user.index';
}
public function edit(){
echo 'user.edit';
}
public function login(){
echo 'user.login';
}
}
//浏览器
当前 URL 模式为:1
User 控制器 index 的操作方法的 URL 为:/./index.php/Home/User/index.html
User 控制器 edit 的操作方法的 URL 为:/./index.php/Home/User/edit.html
User 控制器 login 的操作方法的 URL 为:/./index.php/Home/User/login.html
// ./Application/Home/Conf/config.php
return array(
//...
'URL_MODEL' => 0
);
//浏览器
当前 URL 模式为:0
User 控制器 index 的操作方法的 URL 为:/./index.php?m=Home&c=User&a=index
User 控制器 edit 的操作方法的 URL 为:/./index.php?m=Home&c=User&a=edit
User 控制器 login 的操作方法的 URL 为:/./index.php?m=Home&c=User&a=login
// ./Application/Home/Conf/config.php
return array(
//...
'URL_MODEL' => 2
);
//浏览器
当前 URL 模式为:2
User 控制器 index 的操作方法的 URL 为:/./Home/User/index.html
User 控制器 edit 的操作方法的 URL 为:/./Home/User/edit.html
User 控制器 login 的操作方法的 URL 为:/./Home/User/login.html
//更改后缀
// ./Application/Home/Conf/config.php
return array(
//...
'URL_MODEL' => 2,
'URL_SUFFIX' => 'shtml'
);
//浏览器
当前 URL 模式为:2
User 控制器 index 的操作方法的 URL 为:/./Home/User/index.shtml
User 控制器 edit 的操作方法的 URL 为:/./Home/User/edit.shtml
User 控制器 login 的操作方法的 URL 为:/./Home/User/login.shtml
Rewrite 是通过 URL 重写隐藏应用的入口文件index.php
:
mod_rewrite.so
模块AllowOverride All
htaccess
# httpd.conf,开启下面的项
LoadModule rewrite_module modules/mod_rewrite.so
# 配置根目录(以 D:\path\to\ 为例)
DocumentRoot "D:/path/to/"
# 在 <Directory "D:/path/to/"> 中找到下面的项并设置
AllowOverride All
# ./.htaccess(ThinkPHP 自带的分布式配置文件)已经定义好了
# 重启 Apache 服务器
通过配置 Apache 虚拟主机 Vhost 实现更接近生产环境的 URL
mod_vhost_alias.so
模块httpd-vhosts.conf
hosts
主机头实现转发# hosts,添加下面的项(以 a.bc 为例)
127.0.0.1 a.bc
# httpd.conf,开启下面的项
LoadModule vhost_alias_module modules/mod_vhost_alias.so
# Apache 下的 conf/extra/httpd-vhosts.conf,添加如下代码(除注释)
<VirtualHost *.80>
# D:/path/to/ 为需要映射到的目录
DocumentRoot "D:/path/to/"
ServerName a.bc
ErrorLog "logs/a.bc-error.log"
CustomLog "logs/a.bc-access.log" comon
</VirtualHost>
# 重启 Apache 服务器
ThinkPHP 控制器提供了以下几种方式实现页面跳转和响应:
redirect($addr, $comm, $time, $msg)
$addr
:跳转地址表达式$comm
:附加参数$time
:跳转时间(秒)$msg
:提示信息sucess($msg, $addr, $time)
支持 AJAX 响应。
$msg
:提示信息$addr
:跳转地址$time
:跳转时间(秒)error($msg, $addr, $time)
支持 AJAX 响应。
参数意思同“成功提示跳转”。
ajaxReturn($data, $type)
$data
:要返回的数据$type
:数据格式(如 json
、xml
)控制器定义了 6 个常量,用来快速判断请求的类型:
IS_GET
IS_POST
IS_PUT
IS_DELETE
IS_AJAX
REQUEST_METHOD
(枚举)如果不是用 jQuery 发起 AJAX 的话,需要在请求中添加一个参数才能让服务器知道是一个 AJAX 请求。
默认的参数名称是 ajax
。通过 VAR_AJAX_SUBMIT
配置。
// ./Application/Home/Controller/UserController.class.php
// redirect
//...
class UserController extends Controller {
//以下仅显示以下部分
public function index(){
$this -> redirect('edit', '', 2, '纯跳转'); // 显示“纯跳转”,2 秒后跳转到 ./index.php/Home/User/edit
}
//以下仅显示以上部分
public function edit(){
echo 'user.edit';
}
public function login(){
echo 'user.login';
}
}
// success
public function index(){
$this -> success('成功跳转', U('User/login'), 3);// 成功跳转页面,显示“成功跳转”,3 秒后跳转到 ./index.php/Home/User/login
}
// error
public function index(){
$this -> success('出错了', U('User/login'), 5);// 错误跳转页面,显示“出错了”,5 秒后跳转到 ./index.php/Home/User/login
}
// ./Application/Home/Common/function.php
<?php
function getTestData() {
$data = array();
for($i = 0; $i < 10; $i++) {
$data[$i]['name'] = 'user-' . $i;
$data[$i]['age'] = rand(18, 90);
}
return $data;
}
// ./Application/Home/Controller/UserController.class.php
//...
class UserController extends Controller {
public function index(){
$this -> ajaxReturn(getTestData(), 'json'); //返回 json 的 data 数据
}
}
$_GET
、$_POST
、$_SERVER
(不安全:没有统一的数据过滤,容易发生如SQL注入的攻击)I
函数,方便实现输入变量读取,并自动进行数据安全过滤。I
函数I('变量类型.变量名', ['默认值‘], ['过滤方法'], ['额外数据源'])
// server
// ./Application/Home/Controller/UserController.class.php
//...
class UserController extends Controller {
public function index(){
//下面一个案例只显示以下内容
$server = I('server.'); // $_SERVER 数组的全部值
//下面一个案例只显示以上内容
dump($server);
}
}
$server = I('server.HTTP_HOST'); // 主机名
//get
public function login(){
$user = I('get.user', null);
if($user === 'a') {
//a // 如果访问 ./Home/User/login/user/a 时会跳到这里
} else {
//not a
}
}