结构
框架目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ├─ThinkPHP.php 框架入口文件 ├─Common 框架公共文件 ├─Conf 框架配置文件 ├─Extend 框架扩展目录 ├─Lang 核心语言包目录 ├─Lib 核心类库目录 │ ├─Behavior 核心行为类库 │ ├─Core 核心基类库 │ ├─Driver 内置驱动 │ │ ├─Cache 内置缓存驱动 │ │ ├─Db 内置数据库驱动 │ │ ├─TagLib 内置标签驱动 │ │ └─Template 内置模板引擎驱动 │ └─Template 内置模板引擎 └─Tpl 系统模板目录
|
使项目的入口文件移动到app
目录的外面
修改入口文件index.php
的内容为
1 2 3 4
| <?php define('APP_NAME','app'); define('APP_PATH','./app/'); require '/ThinkPHP框架所在目录/ThinkPHP.php';
|
项目目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ├─index.php 项目入口文件 ├─Common 项目公共文件目录 ├─Conf 项目配置目录 ├─Lang 项目语言目录 ├─Lib 项目类库目录 │ ├─Action Action类库目录 │ ├─Behavior 行为类库目录 │ ├─Model 模型类库目录 │ └─Widget Widget类库目录 ├─Runtime 项目运行时目录 │ ├─Cache 模板缓存目录 │ ├─Data 数据缓存目录 │ ├─Logs 日志文件目录 │ └─Temp 临时缓存目录 └─Tpl 项目模板目录
|
项目配置简介
配置
每个项目都有一个独立的配置文件(位于项目目录的Conf/config.php
),配置文件的定义格式均采用PHP返回数组的方式,例如:
1 2 3 4 5 6
| return array( '配置参数' => '配置值', );
|
一旦有需要,我们就可以在项目配置文件中添加相关配置项目。通常我们提到的添加配置项目,就是指在项目配置文件中添加:
控制器
需要为每个模块定义一个控制器类,控制器类的命名规范是:
模块名+Action.class.php
(模块名采用驼峰法并且首字母大写)
系统的默认模块是Index,对应的控制器就是项目目录下面的Lib/Action/IndexAction.class.php
,类名和文件名一致。默认操作是index,也就是控制器的一个public方法。初次生成项目目录结构的时候,系统已经默认生成了一个默认控制器(就是之前看到的欢迎页面),我们把index方法改成下面的代码:
1 2 3 4 5
| class IndexAction extends Action { public function index(){ echo 'hello,world!'; } }
|
URL请求
入口文件是项目的单一入口,对项目的所有请求都定向到项目的入口文件,系统会从URL参数中解析当前请求的模块和操作,我们之前访问的URL地址中没有任何参数,因此系统会访问默认模块(Index)的默认操作(index),因此下面的访问和之前是等效的:
1
| http://localhost/app/index.php/Index/index
|
这种URL模式就是系统默认的PATHINFO模式,不同的URL模式获取模块和操作的方法不同,ThinkPHP支持的URL模式有四种:普通模式、PATHINFO、REWRITE和兼容模式。
普通模式
也就是传统的GET传参方式来指定当前访问的模块和操作,例如:
1
| http://localhost/app/?m=module&a=action&var=value
|
视图
ThinkPHP内置了一个编译型模板引擎,也支持原生的PHP模板,并且还提供了包括Smarty在内的模板引擎驱动。和Smarty不同,ThinkPHP在渲染模板的时候如果不指定模板,则会采用系统默认的定位规则,其定义规范是 Tpl/模块名/操作名.html,所以,Index模块的index操作的默认模板文件位于项目目录下面的Tpl/Index/index.html。
1 2 3 4 5 6 7 8
| <html> <head> <title>hello {$name}</title> </head> <body> hello, {$name}! </body> </html>
|
要输出视图,必须在控制器方法中进行模板渲染输出操作,例如:
1 2 3 4 5 6
| class IndexAction extends Action { public function index(){ $this->name = 'thinkphp'; // 进行模板变量赋值 $this->display(); } }
|
display方法中我们没有指定任何模板,所以按照系统默认的规则输出了Index/index.html模板文件。
变量使用
变量获取
传统获取方式
1 2 3 4 5
| $id = $_GET['id']; $name = $_POST['name']; $value = $_SESSION['var']; $name = $_COOKIE['name']; $file = $_SERVER['PHP_SELF'];
|
Action类动态获取
系统的Action类提供了对系统变量的增强获取方法,包括对GET、POST、PUT、REQUEST、SESSION、COOKIE、SERVER和GLOBALS参数,除了获取变量值外,还提供变量过滤和默认值支持,用法很简单,只需要在Action中调用下面方法:
1 2 3 4 5
| $id = $this->_get('id'); $name = $this->_post('name'); $value = $this->_session('var'); $name = $this->_cookie('name'); $file = $this->_server('PHP_SELF');
|
调用格式为:
1
| $this->方法名("变量名",["过滤方法"],["默认值"])
|
方法名可支持:
方法名 |
含义 |
_get |
获取GET参数 |
_post |
获取POST参数 |
_param |
自动判断请求类型获取GET、POST或者PUT参数 |
_request |
获取REQUEST参数 |
_put |
获取PUT参数 |
_session |
获取$_SESSION参数 |
_cookie |
获取$_COOKIE参数 |
_server |
获取$_SERVER参数 |
_globals |
获取$GLOBALS参数 |
获取URL参数
在某些情况下面,我们还有一种获取URL参数的特殊需求,一般来说,获取URL参数是采用get变量的方式就够用了,但是对于我们定制过的URL,或者采用了路由的情况下面,URL的参数可能会没有规律,这个时候,我们可以采用另外一种方式来获取。
例如,当前的URL地址是:
要获取其中的参数,可以用:
1 2 3
| $this->_param(0); $this->_param(1); $this->_param(2);
|
输出
在控制器中给模板变量赋值:
1 2 3
| $name = 'ThinkPHP'; $this->assign('name',$name); $this->display();
|
在模板中使用该变量:
系统变量
普通的模板变量需要首先赋值后才能在模板中输出,但是系统变量则不需要,可以直接在模板中输出,系统变量的输出通常以{$Think 打头,例如:
1 2 3 4
| {$Think.server.script_name} {$Think.session.user_id} {$Think.get.pageNumber} {$Think.cookie.name}
|
支持输出$_SERVER、$_ENV、 $_POST、 $_GET、 $_REQUEST、$_SESSION和 $_COOKIE变量
。
使用函数
简单用法
编译后:
1
| <?php echo (md5($data['name'])); ?>
|
多个参数
1
| {$create_time|date="y-m-d",
|
表示date函数传入两个参数,每个参数用逗号分割,这里第一个参数是y-m-d,第二个参数是前面要输出的create_time变量,因为该变量是第二个参数,因此需要用###标识变量位置,编译后的结果是:
1
| <?php echo (date("y-m-d",$create_time)); ?>
|
默认值
1
| {$user.nickname|default="这家伙很懒,什么也没留下"}
|
控制器使用
Action参数绑定的原理是把URL中的参数(不包括分组、模块和操作名)和控制器的操作方法中的参数(按变量名)进行绑定。
简单使用
例如,我们给Blog模块定义了两个操作方法read和archive方法,并且给read操作需要指定一个id参数,archive方法指定年份(year)和月份(month)两个参数。为了演示方便,我们省去了具体操作方法的业务代码,仅仅用echo 输出当前的参数。
1 2 3 4 5 6 7 8
| class BlogAction extends Action{ public function read($id){ echo 'id='.$id; } public function archive($year='2012',$month='01'){ echo 'year='.$year.'&month='.$month; } }
|
URL的访问地址分别是
输出的结果
文件上传
UploadFile.class.php
位于ThinkPHP/Extend/Library/ORG/Net/
功能
- 基本上传功能
- 支持批量上传
- 支持生成图片缩略图
- 自定义参数上传
- 上传检测(包括大小、后缀和类型)
- 支持覆盖方式上传
- 支持上传类型、附件大小、上传路径定义
- 支持哈希或者日期子目录保存上传文件
- 支持动态定义子目录保存文件
- 上传图片的安全性检测
- 支持上传文件命名规则
- 支持对上传文件的Hash验证
简单的上传
表单
1 2 3 4
| <form id="upload" method='post' action="!-URL-!/upload/" enctype="multipart/form-data"> <input name="image" type="file" /> <input type="submit" value="提交" > </form>
|
注意,表单必须添加**enctype="multipart/form-data"
**属性才能支持文件上传功能。
操作
在Action控制器中添加upload操作方法如下
1 2 3 4 5 6 7 8 9 10 11 12 13
| public function upload() { import('ORG.Net.UploadFile'); $upload = new UploadFile(); $upload->maxSize = 3145728 ; $upload->allowExts = array('jpg', 'gif', 'png', 'jpeg'); $upload->savePath = './Public/Uploads/'; if(!$upload->upload()) { $this->error($upload->getErrorMsg()); }else{ $this->success('上传成功!'); } }
|
参数设置
实例化上传类
1 2
| import('ORG.Net.UploadFile'); $upload = new UploadFile();
|
常用参数
maxSize |
文件上传的最大文件大小(以字节为单位)默认为-1 不限大小 |
savePath |
文件保存路径(必须) |
saveRule |
上传文件的保存规则,必须是一个无需任何参数的函数名,例如可以是 time、 uniqid com_create_guid 等,但必须能保证生成的文件名是唯一的,默认是uniqid |
hashType |
上传文件的哈希验证方法,默认是md5_file |
autoCheck |
是否自动检测附件,默认为自动检测 |
uploadReplace |
存在同名文件是否是覆盖 |
allowExts |
允许上传的文件后缀(留空为不限制),使用数组设置,默认为空数组 |
allowTypes |
允许上传的文件类型(留空为不限制),使用数组设置,默认为空数组 |
thumb |
是否需要对图片文件进行缩略图处理,默认为false |
thumbMaxWidth |
缩略图的最大宽度,多个使用逗号分隔 |
thumbMaxHeight |
缩略图的最大高度,多个使用逗号分隔 |
thumbPrefix |
缩略图的文件前缀,默认为thumb_ |
thumbSuffix |
缩略图的文件后缀,默认为空 |
thumbPath |
缩略图的保存路径,留空的话取文件上传目录本身 |
thumbFile |
指定缩略图的文件名 |
thumbExt |
指定缩略图的扩展名 |
thumbRemoveOrigin |
生成缩略图后是否删除原图 |
autoSub |
是否使用子目录保存上传文件 |
subType |
子目录创建方式,默认为hash,可以设置为hash、date或者custom |
subDir |
子目录名称 subType为custom方式后有效 |
dateFormat |
子目录方式为date的时候指定日期格式 |
hashLevel |
子目录保存的层次,默认为一层 |
设置方法
1 2 3 4 5 6 7 8 9 10
| $upload->savePath = './Uploads/';
$upload->thumb = true;
$upload->thumbPrefix = 'm_,s_';
$upload->thumbMaxWidth = '200,50';
$upload->thumbMaxHeight = '200,50';
|
或者在实例化的同时传入上传参数,例如:
1 2 3 4 5 6 7
| import('ORG.Net.UploadFile'); $config['savePath'] = './Uploads/'; $config['thumb'] = true; $config['thumbPrefix'] = 'm_,s_'; $config['thumbMaxWidth'] = '200,50'; $config['thumbMaxHeight'] = '200,50'; $upload = new UploadFile($config);
|
单\多文件上传
单文件
uploadOne方法表示每次执行只上传指定的一个文件,并且如果上传成功的话uploadOne方法的返回值就是成功上传的文件信息,和getUploadFileInfo方法不同的是,这个文件信息是一个仅包含单个文件信息的一维数组。如果发生错误,依然是通过getErrorMsg方法获取错误信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import("ORG.Net.UploadFile"); $upload = new UploadFile(); foreach ($_FILES as $key=>$file){ if(!empty($file['name'])) { $upload->autoSub = true; $upload->subType = 'date'; $info = $upload->uploadOne($file); if($info){ M('Photo')->add($info); }else{ $this->error($upload->getErrorMsg()); } } }
|
多文件
上传类默认就支持多文件上传,只需要修改表单页面:
如果需要使用多个文件上传,只需要修改表单,把
1
| <input type='file' name='image'>
|
改为
1 2 3
| <input type='file' name='image1'> <input type='file' name='image2'> <input type='file' name='image3'>
|
模型内数据操作
连接数据库
首先在数据库thinkphp中创建一个think_data数据表(以mysql数据库为例):
1 2 3 4 5 6 7 8 9
| CREATE TABLE IF NOT EXISTS `think_data` ( `id` int(8) unsigned NOT NULL AUTO_INCREMENT, `data` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ; INSERT INTO `think_data` (`id`, `data`) VALUES (1, 'thinkphp'), (2, 'php'), (3, 'framework');
|
如果我们需要读取数据库中的数据,就需要在项目配置文件中(App/home/conf/config.php
)添加数据库连接信息如下:
1 2 3 4 5 6 7 8
| // 添加数据库配置信息 'DB_TYPE' => 'mysql', // 数据库类型 'DB_HOST' => 'localhost', // 服务器地址 'DB_NAME' => 'thinkphp', // 数据库名 'DB_USER' => 'root', // 用户名 'DB_PWD' => '', // 密码 'DB_PORT' => 3306, // 端口 'DB_PREFIX' => 'think_', // 数据库表前缀
|
或者:
1
| 'DB_DSN' => 'mysql://root@localhost:3306/thinkphp'
|
读取数据
修改控制器方法,添加读取数据的代码:
1 2 3 4 5 6 7
| class IndexAction extends Action { public function index(){ $Data = M('Data'); $this->data = $Data->select(); $this->display(); } }
|
M('Data')
实例化后,就可以对think_data数据表(think_ 是我们在项目配置文件中定义的数据表前缀)进行操作(包括CURD)了
定义好控制器后,我们修改模板文件,添加数据输出标签如下:
1 2 3 4 5 6 7 8 9 10
| <html> <head> <title>Select Data</title> </head> <body> <volist name="data" id="vo"> {$vo.id}--{$vo.data}<br/> </volist> </body> </html>
|
volist标签
是内置模板引擎用于输出数据集的标签。{$vo.id}
和 {$vo.data}
的用法和Smarty类似,就是用于输出数据的字段,这里就表示输出think_data表的id和data字段的值。
我们访问
输出:
1 2 3
| 1--thinkphp 2--php 3--framework
|
CURD
即数据库的Create.Update.Read.Delete,与ThinkPHP中的 add.save.select.delete一致。
创建数据(Create)
Create操作通常会通过表单来提交数据,首先,我们在项目的Tpl/Form 目录下面创建一个add.html 模板文件,内容为
1 2 3 4 5
| <FORM method="post" action="__URL__/insert"> 标题:<INPUT type="text" name="title"><br/> 内容:<TEXTAREA name="content" rows="5" cols="45"></TEXTAREA><br/> <INPUT type="submit" value="提交"> </FORM>
|
然后再项目中Action目录下创建FormAction.class.php
文件,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class FormAction extends Action{ public function insert(){ $Form = D('Form'); if($Form->create()) { $result = $Form->add(); if($result) { $this->success('操作成功!'); }else{ $this->error('写入错误!'); } }else{ $this->error($Form->getError()); } } } }
|
如果主键是自增类型的话,add方法的返回值就是该主键的值。不是自增主键的话,返回值表示插入数据的个数。如果返回false则表示写入出错。
读取数据
1 2 3 4 5 6 7 8 9 10 11
| public function read($id=0){ $Form = M('Form'); $data = $Form->find($id); if($data) { $this->data = $data; }else{ $this->error('数据错误'); } $this->display(); }
|
更新数据
数据的更新操作在ThinkPHP使用save方法,可以看到,我们同样可以使用create方法创建表单提交的数据,而save方法则会自动把当前的数据对象更新到数据库,而更新的条件其实就是表的主键,这就是我们在编辑页面要把主键的值作为隐藏字段一起提交的原因。
如果更新操作不依赖表单的提交的话,就可以写成:
1 2 3 4 5 6
| $Form = M("Form");
$data['id'] = 5; $data['title'] = 'ThinkPHP'; $data['content'] = 'ThinkPHP3.1版本发布'; $Form->save($data);
|
删除数据
1 2 3 4
| $User = M("User"); $User->where('id=5')->delete(); $User->delete('1,2,5'); $User->where('status=0')->delete();
|
查询
三个基础查询
以字符串为条件
不够安全
1 2 3
| $User = M("User"); $User->where('type=1 AND status=1')->select();
|
以数组为条件
较为常用
1 2 3 4 5 6
| $User = M("User"); $condition['name'] = 'thinkphp'; $condition['status'] = 1;
$User->where($condition)->select();
|
以对象方式来查询
以stdClass内置对象为例
1 2 3 4 5 6 7
| $User = M("User");
$condition = new stdClass(); $condition->name = 'thinkphp'; $condition->status= 1; $User->where($condition)->select();
|
快捷查询
不同字段的相同查询
1 2 3 4
| $User = M("User"); $map['name|title'] = 'thinkphp';
$User->where($map)->select();
|
不同字段的不同查询
1 2 3 4
| $User = M("User"); $map['name|title'] = 'thinkphp';
$User->where($map)->select();
|
SQL查询
内置的ORM和ActiveRecord模式实现了方便的数据存取操作,而且新版增加的连贯操作功能更是让这个数据操作更加清晰,但是ThinkPHP仍然保留了原生的SQL查询和执行操作支持,为了满足复杂查询的需要和一些特殊的数据操作,SQL查询的返回值因为是直接返回的Db类的查询结果,没有做任何的处理。主要包括下面两个方法:
query方法
1
| query($sql,$parse=false)
|
sql
:要查询的SQL语句
parse
:是否需要解析SQL
1 2
| $Model = new Model() $Model->query("select * from think_user where status=1");
|
execute方法
1
| execute($sql,$parse=false)
|
sql
:要查询的SQL语句
parse
:是否需要解析SQL
1 2
| $Model = new Model() $Model->execute("update think_user set name='thinkPHP' where status=1");
|
连贯操作
例如$User->where('status=1')->order('create_time')->limit(10)->select();
常用用法
WHERE
where 用于查询或者更新条件的定义
用法 |
where($where) |
参数 |
where(必须):查询或者操作条件,支持字符串、数组和对象 |
返回值 |
当前模型实例 |
备注 |
如果不调用where方法,默认不会执行更新和删除操作 |
TABLE
table 定义要操作的数据表名称,动态改变当前操作的数据表名称,需要写数据表的全名,包含前缀,可以使用别名和跨库操作
用法 |
table($table) |
参数 |
table(必须):数据表名称,支持操作多个表,支持字符串、数组和对象 |
返回值 |
当前模型实例 |
备注 |
如果不调用table方法,会自动获取模型对应或者定义的数据表 |
DATA
data 可以用于新增或者保存数据之前的数据对象赋值
用法 |
data($data) |
参数 |
data(必须):数据,支持数组和对象 |
返回值 |
当前模型实例 |
备注 |
如果不调用data方法,则会取当前的数据对象或者传入add和save的数据 |
FIELD
field 用于定义要查询的字段
用法 |
field($field,$except=false) |
参数 |
field(必须):字段名,支持字符串和数组,支持指定字段别名;如果为true则表示显式或者数据表的所有字段。 except(可选):是否排除,默认为false,如果为true表示定义的字段为数据表中排除field参数定义之外的所有字段。 |
返回值 |
当前模型实例 |
备注 |
如果不调用field方法,则默认返回所有字段,和field(’*’)等效 |
ORDER
order 用于对操作结果排序
用法 |
order($order) |
参数 |
order(必须):排序的字段名,支持字符串和数组,支持多个字段排序 |
返回值 |
当前模型实例 |
备注 |
如果不调用order方法,按照数据库的默认规则 |
1
| \app\common\entity\Article::where('category', $category)->order('sort', 'asc')->select();
|
LIMIT
limit 用于定义要查询的结果限制(支持所有的数据库类型)
用法 |
limit($limit) |
参数 |
limit(必须):限制数量,支持字符串 |
返回值 |
当前模型实例 |
备注 |
如果不调用limit方法,则表示没有限制 |
GROUP
group 用于数据库的group查询支持
用法 |
group($group) |
参数 |
group(必须):group的字段名,支持字符串 |
返回值 |
当前模型实例 |
备注 |
无 |
UNION
union 用于数据库的union查询支持
用法 |
union($union,$all=false) |
参数 |
union(必须):union操作,支持字符串、数组和对象 all(可选):是否采用UNION ALL 操作,默认为false |
返回值 |
当前模型实例 |
备注 |
Union方法支持多次调用 |
常用方法
方法 |
作用 |
支持的参数类型 |
where |
用于查询或者更新条件的定义 |
字符串、数组和对象 |
table |
用于定义要操作的数据表名称 |
字符串和数组 |
alias |
用于给当前数据表定义别名 |
字符串 |
data |
用于新增或者更新数据之前的数据对象赋值 |
数组和对象 |
field |
用于定义要查询的字段(支持字段排除) |
字符串和数组 |
order |
用于对结果排序 |
字符串和数组 |
limit |
用于限制查询结果数量 |
字符串和数字 |
group |
用于对查询的group支持 |
字符串 |
filter |
用于数据过滤 |
字符串 |