ThinkPHP
简介
- 国产、基于Apache 2.0协议开源,对商业用途友好
- 基于PHP 5.3及以上版本(一系列新特性,如命名空间)
- 核心可定制(应用模式和CBD架构)
- 编译机制(压缩合并、模板编译,和Java的编译不是一个概念)
解压后在浏览器中访问页面(目录),然后更改./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() 中的内容,即可更改对应的页面。在入口文件中绑定模块后,默认访问的就是这个模块。
打印变量
MVC分层架构
- 控制器(Controller):负责用户请求的调度、处理业务逻辑
- 模型(Model):负责业务数据的处理、与数据库的交互
- 视图(View):提供了展示数据的各种方式
优点:将业务逻辑、视图展示和数据处理分离开,降低设计、管理的难度,代码也更具结构性,更容易维护、重用。(合理分工带来的效率提升)
整个请求响应的过程类比
| 用户
↕
C(服务员)
↕ ↕
M(厨师)↔ V(摆盘)
↕
DB(仓库)
|
- C 记录客人点了什么菜、要求;根据不同种类的菜,交给不同的 M;
- M 根据订单到DB取原材料(与数据库交互);经过烹饪完成订单上的菜品,交给 V;
- V根据相应菜品的摆盘方案,进行摆盘装饰(视图的渲染输出);
- 由 C 给客人上菜。
配置
ThinkPHP框架配置文件自动加载顺序
- 惯例配置(
./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 函数读取配置:
读取全部配置项:
读取配置项名称为 name 的配置项:
读取配置项名称为 name 的配置项,如未配置则返回 default:
| C('name', null, 'default')
|
读取二维数组配置,父子项之间以点号连接:
配置名称大小写
配置名称不区分大小写,但在二维数组配置读取的参数中,parent严格区分大小写。
动态配置
通过 C 函数进行动态配置,以在程序逻辑中临时改变配置。
设置配置项名称为 name 的配置项:
批量配置:
$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'
|
控制器
简介
- 控制器是一个 PHP 类,需要继承 ThinkPHP 的核心类
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";
}
}
|
调用的四种方式
URL模式
4种模式
通过 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...
- 第二个参数支持数组、字符串两种定义方式
- 类 UNIX 系统对 URL 大小写敏感,通过配置
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>';
}
}
|
PathInfo模式
| // ./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
|
Rewrite模式
| // ./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
|
本地 Apache 服务器实现 Rewrite 模式
Rewrite 是通过 URL 重写隐藏应用的入口文件index.php:
- Apache 开启
mod_rewrite.so 模块
AllowOverride All
- 定义分布式配置文件
htaccess
- 配置完后必须重启 Apache 服务器才能生效
| # 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
通过配置 Apache 虚拟主机 Vhost 实现更接近生产环境的 URL
- Apache 开启
mod_vhost_alias.so 模块
- 配置
httpd-vhosts.conf
- 添加
hosts 主机头实现转发
- 配置完后必须重启 Apache 服务器才能生效
| # 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 控制器提供了以下几种方式实现页面跳转和响应:
- 重定向
- 成功提示跳转
- 错误提示跳转
- 实现 Ajax 数据返回
重定向
| redirect($addr, $comm, $time, $msg)
|
$addr:跳转地址表达式
$comm:附加参数
$time:跳转时间(秒)
$msg:提示信息
成功提示跳转
| sucess($msg, $addr, $time)
|
支持 AJAX 响应。
$msg:提示信息
$addr:跳转地址
$time:跳转时间(秒)
错误提示跳转
| error($msg, $addr, $time)
|
支持 AJAX 响应。
参数意思同“成功提示跳转”。
实现 Ajax 数据返回
$data:要返回的数据
$type:数据格式(如 json、xml)
判断请求的类型
控制器定义了 6 个常量,用来快速判断请求的类型:
IS_GET
IS_POST
IS_PUT
IS_DELETE
IS_AJAX
REQUEST_METHOD(枚举)
AJAX 请求的识别参数
如果不是用 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注入的攻击)
- ThinkPHP 提供了
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
}
}
|
来源
【极客学院】PHP全套教学视频_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili