欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

ThinkPHP3.1快速入门(4)连贯操作

shiping1 的头像
上一篇我们详细描述了查询语言的用法,但是查询语言仅仅解决了查询或者操作条件的问题,更多的配合还需要使用模型提供的连贯操作方法。

介绍

连贯操作可以有效的提高数据存取的代码清晰度和开发效率,并且支持所有的CURD操作,也是ThinkPHP的ORM中的一个亮点。使用也比较简单, 假如我们现在要查询一个User表的满足状态为1的前10条记录,并希望按照用户的创建时间排序 ,代码如下:
  1. $User->where('status=1')->order('create_time')->limit(10)->select();
复制代码
 
这里的whereorderlimit方法就称之为连贯操作方法,除了select方法必须放到最后一个外(因为select方法并不是连贯操作方法),连贯操作的方法调用顺序没有先后,例如,下面的代码和上面的等效:
  1. $User->order('create_time')->limit(10)->where('status=1')->select();
复制代码
 
其实不仅仅是查询方法可以使用连贯操作,包括所有的CURD方法都可以使用,例如:
  1. $User->where('id=1')->field('id,name,email')->find(); 
  2. $User->where('status=1 and id=1')->delete();
复制代码
 
连贯操作仅在当次查询或者操作有效,完成后会自动清空连贯操作的所有传值(有个别特殊的连贯操作会记录当前的传值,如cache连贯操作)。简而言之,连贯操作的结果不会带入以后的查询。
系统支持的连贯操作方法有:
方法作用支持的参数类型
where用于查询或者更新条件的定义字符串、数组和对象
table用于定义要操作的数据表名称字符串和数组
alias用于给当前数据表定义别名字符串
data用于新增或者更新数据之前的数据对象赋值数组和对象
field用于定义要查询的字段(支持字段排除)字符串和数组
order用于对结果排序字符串和数组
limit用于限制查询结果数量字符串和数字
page用于查询分页(内部会转换成limit)字符串和数字
group用于对查询的group支持字符串
having用于对查询的having支持字符串
join*用于对查询的join支持字符串和数组
union*用于对查询的union支持字符串、数组和对象
distinct用于查询的distinct支持布尔值
lock用于数据库的锁机制布尔值
cache用于查询缓存支持多个参数(以后在缓存部分再详细描述)
relation用于关联查询(需要关联模型扩展支持)字符串
validate用于数据自动验证数组
auto用于数据自动完成数组
filter用于数据过滤字符串
scope*用于命名范围字符串、数组
所有的连贯操作都返回当前的模型实例对象(this),其中带*标识的表示支持多次调用。

用法

由于连贯操作的使用往往涉及到多个方法的联合使用,下面大概介绍下各个连贯操作的基本用法:

WHERE

where 用于查询或者更新条件的定义
用法where($where)
参数where(必须):查询或者操作条件,支持字符串、数组和对象
返回值当前模型实例
备注如果不调用where方法,默认不会执行更新和删除操作
Where方法是使用最多的连贯操作方法,更详细的用法请参考:快速入门(3)查询语言

TABLE

table  定义要操作的数据表名称,动态改变当前操作的数据表名称,需要写数据表的全名,包含前缀,可以使用别名和跨库操作
用法table($table)
参数table(必须):数据表名称,支持操作多个表,支持字符串、数组和对象
返回值当前模型实例
备注如果不调用table方法,会自动获取模型对应或者定义的数据表
用法示例:
  1. $Model->Table('think_user user')->where('status>1')->select();
复制代码
 
也可以在table方法中跨库操作,例如:
  1. $Model->Table('db_name.think_user user')->where('status>1')->select();
复制代码
 
Table方法的参数支持字符串和数组,数组方式的用法:
  1. $Model->Table(array('think_user'=>'user','think_group'=>'group'))->where('status>1')->select();
复制代码
 
使用数组方式定义的优势是可以避免因为表名和关键字冲突而出错的情况。
一般情况下,无需调用table方法,默认会自动获取当前模型对应或者定义的数据表。

DATA

data  可以用于新增或者保存数据之前的数据对象赋值
用法data($data)
参数data(必须):数据,支持数组和对象
返回值当前模型实例
备注如果不调用data方法,则会取当前的数据对象或者传入add和save的数据
使用示例:
  1. $Model->data($data)->add();
  2. $Model->data($data)->where('id=3')->save();
复制代码
 
Data方法的参数支持对象和数组,如果是对象会自动转换成数组。如果不定义data方法赋值,也可以使用create方法或者手动给数据对象赋值的方式。

模型的data方法除了创建数据对象之外,还可以读取当前的数据对象,
例如:
  1. $this->find(3);
  2. $data = $this->data();
复制代码
 

FIELD

field  用于定义要查询的字段
用法field($field,$except=false)
参数

field(必须):字段名,支持字符串和数组,支持指定字段别名;如果为true则表示显式或者数据表的所有字段。


except(可选):是否排除,默认为false,如果为true表示定义的字段为数据表中排除field参数定义之外的所有字段。

返回值当前模型实例
备注如果不调用field方法,则默认返回所有字段,和field('*')等效
使用示例:
  1. $Model->field('id,nickname as name')->select();
  2. $Model->field(array('id','nickname'=>'name'))->select();
复制代码
 
如果不调用field方法或者field方法传入参数为空的话,和使用field('*')是等效的。
如果需要显式的传入所有的字段,可以使用下面的方法:
  1. $Model->field(true)->select();
复制代码
 
但是我们更建议只获取需要显式的字段名,或者采用字段排除方式来定义,例如:
  1. $Model->field('status',true)->select();
复制代码
 
表示获取除了status之外的所有字段。

ORDER

order  用于对操作结果排序
用法order($order)
参数order(必须):排序的字段名,支持字符串和数组,支持多个字段排序
返回值当前模型实例
备注如果不调用order方法,按照数据库的默认规则
使用示例:
  1. order('id desc') 
复制代码
 
排序方法支持对多个字段的排序
  1. order('status desc,id asc')
复制代码
 
order方法的参数支持字符串和数组,数组的用法如下:
  1. order(array('status'=>'desc','id'))
复制代码
 

LIMIT

limit  用于定义要查询的结果限制(支持所有的数据库类型)
用法limit($limit)
参数limit(必须):限制数量,支持字符串
返回值当前模型实例
备注如果不调用limit方法,则表示没有限制
备注 如果不调用limit方法,则表示没有限制
我们知道不同的数据库类型的limit用法是不尽相同的,但是在ThinkPHP的用法里面始终是统一的方法,也就是limit('offset,length') ,无论是Mysql、SqlServer还是Oracle数据库,都是这样使用,系统的数据库驱动类会负责解决这个差异化。
使用示例:
  1. limit('1,10')
复制代码
 
也可以用下面的两个参数的写法,是等效的:
  1. limit(1,10)
复制代码
 
如果使用
  1. limit('10')
复制代码
 
等效于
  1. limit('0,10')
复制代码
 

PAGE

page 用于定义要查询的数据分页
用法page($page)
参数page(必须):分页,支持字符串
返回值当前模型实例
备注
Page操作方法可以更加快速的进行分页查询。
Page方法的用法和limit方法类似,格式为:
  1. Page('page[,listRows]')
复制代码
 
Page表示当前的页数,listRows表示每页显示的记录数。例如:
  1. Page('2,10')
复制代码
 
表示每页显示10条记录的情况下面,获取第2页的数据。
listRow如果不写的话,会读取limit('length') 的值,例如:
  1. limit(25)->page(3);
复制代码
 
表示每页显示25条记录的情况下面,获取第3页的数据。
如果limit也没有设置的话,则默认为每页显示20条记录。
page方法也支持传入二个参数,例如:
  1. $this->page(5,25)->select();
复制代码
 
和之前的用法
  1. $this->page('5,25')->select();
复制代码
 
等效。

GROUP

group 用于数据库的group查询支持
用法group($group)
参数group(必须):group的字段名,支持字符串
返回值当前模型实例
备注
使用示例:
  1. group('user_id')
复制代码
 
Group方法的参数只支持字符串

HAVING

having 用于数据库的having查询支持
用法having($having)
参数having(必须):having,支持字符串
返回值当前模型实例
备注
使用示例:
  1. having('user_id>0')
复制代码
 
having方法的参数只支持字符串

JOIN

join 用于数据库的join查询支持
用法join($join)
参数join(必须):join操作,支持字符串和数组
返回值当前模型实例
备注join方法支持多次调用
使用示例:
  1. $Model->join(' work ON artist.id = work.artist_id')->join('card ON artist.card_id = card.id')->select();
复制代码
 
默认采用LEFT JOIN 方式,如果需要用其他的JOIN方式,可以改成
  1. $Model->join('RIGHT JOIN work ON artist.id = work.artist_id')->select();
复制代码
 
如果join方法的参数用数组的话,只能使用一次join方法,并且不能和字符串方式混合使用。
例如:
  1. join(array(' work ON artist.id = work.artist_id','card ON artist.card_id = card.id'))
复制代码
 

UNION

union 用于数据库的union查询支持
用法union($union,$all=false)
参数union(必须):union操作,支持字符串、数组和对象
all(可选):是否采用UNION ALL 操作,默认为false
返回值当前模型实例
备注Union方法支持多次调用
使用示例:
  1. $Model->field('name')
  2.       ->table('think_user_0')
  3.       ->union('SELECT name FROM think_user_1')
  4.       ->union('SELECT name FROM think_user_2')
  5.       ->select();
复制代码
 
数组用法:
  1. $Model->field('name')
  2.       ->table('think_user_0')
  3.       ->union(array('field'=>'name','table'=>'think_user_1'))
  4.       ->union(array('field'=>'name','table'=>'think_user_2'))
  5.       ->select();
复制代码
 
或者
  1. $Model->field('name')
  2.       ->table('think_user_0')
  3.       ->union(array('SELECT name FROM think_user_1','SELECT name FROM think_user_2'))
  4.       ->select();
复制代码
 
支持UNION ALL 操作,例如:
  1. $Model->field('name')
  2.       ->table('think_user_0')
  3.       ->union('SELECT name FROM think_user_1',true)
  4.       ->union('SELECT name FROM think_user_2',true)
  5.       ->select();
复制代码
 
或者
  1. $Model->field('name')
  2.       ->table('think_user_0')
  3.       ->union(array('SELECT name FROM think_user_1','SELECT name FROM think_user_2'),true)
  4.       ->select();
复制代码
 
每个union方法相当于一个独立的SELECT语句。
注意:UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。

DISTINCT

distinct 查询数据的时候进行唯一过滤
用法distinct($distinct)
参数distinct(必须):是否采用distinct,支持布尔值
返回值当前模型实例
备注
使用示例:
  1. $Model->Distinct(true)->field('name')->select();
复制代码
 

LOCK

lock 用于查询或者写入锁定
用法lock($lock)
参数lock(必须):是否需要锁定,支持布尔值
返回值当前模型实例
备注join方法支持多次调用
Lock方法是用于数据库的锁机制,如果在查询或者执行操作的时候使用:
  1. lock(true)
复制代码
 
就会自动在生成的SQL语句最后加上 FOR UPDATE或者FOR UPDATE NOWAIT(Oracle数据库)。

VALIDATE

validate 用于数据的自动验证
用法validate($validate)
参数validate(必须):自动验证定义
返回值当前模型实例
备注只能和create方法配合使用
validate方法用于数据的自动验证,我们会在数据验证部分详细描述。

AUTO

auto 用于数据自动完成
用法auto($auto)
参数auto(必须):定义自动完成
返回值当前模型实例
备注auto方法只能配合create方法使用
auto方法用于数据的自动完成操作,具体使用我们会在数据自动完成部分描述。

SCOPE

scope 用于模型的命名范围
用法scope($scope)
参数scope(必须):命名范围定义
返回值当前模型实例
备注scope方法其实是连贯操作的预定义
scope方法的具体用法可以参考:3.1的新特性 命名范围

FILTER

filter 用于数据的安全过滤
用法filter($filter)
参数filter(必须):过滤方法名
返回值当前模型实例
备注filter方法一般用于写入和更新操作
filter方法用于对数据对象的安全过滤,例如:
  1. $Model->data($data)->filter('strip_tags')->add();
复制代码
 
目前filter方法不支持多个方法的过滤。

总结

连贯操作为我们的数据操作带来了很大的便捷之处,并且只要SQL可以实现的操作,基本上都可以用ThinkPHP的连贯操作来实现,并且不用考虑数据库之间的表达差异,具有可移植性。后面会和大家讲解如何操作和获取变量。

来自  
http://www.thinkphp.cn/info/116.html

huyiwei05月15日
原来这里有啊,好吧!
 
☆Andy☆2015年01月21日
TP 搞这种飞机 画蛇添足了 好好框架 加 这些复杂 记忆的快疯了 哎 直接 SQL OK ,sql 很通用 吗 基本的提供了就可以了
回复神泣04月02日
弱智儿,不学也罢
 
宁灬不凡2014年05月19日
以前一直以为还是用原生的sql语法方便,后来实际做一些项目了,才发现tp封装的这些方法是很方便的,因为封装之后就可以不用关心数据操作的细节了。
crabyan2014年04月28日
基本不想看thinkphp提供的这些复杂得上天的数据库语法结构,除非很特殊的需要自动生成数据库查询语句的操作,否则还是用原生的比较好
shankesgk22014年03月03日
只能说:您辛苦了。这些东西记起来也辛苦。
liujiachen2013年11月28日
不知道多表查询方不方便
xieguoen2013年09月03日
Oracle 是没有limit概念的
回复SimpleCMS2013年09月04日
Oracle rownum,但是需要慎用正确使用rownum!
回复SimpleCMS2013年09月04日
Oracle rownum,但是需要慎用正确使用rownum!
mxmx2013年08月02日
  1. echo 'Hello,thinkphp...';
复制代码
 
复制代码
 
helum2013年06月30日
怎么我看了下好像没有select a from b的形式的,基本的查询语句都是select * from b 这种形式然后再获取a字段内容的,这样子不是耗费查询时间么?
回复See2013年07月24日
$Model->field('a')->table('b')->select();
回复星野天河2014年12月24日
一般情况下是M('user')->find(5)->getField('title')
回复See2013年07月24日
$Model->field('a')->table('b')->select();
回复星野天河2014年12月24日
一般情况下是M('user')->find(5)->getField('title')
whilelie2013年06月10日
类似于linq方法
crazyphp2013年05月07日
求助
无法加载模块:Form
错误位置
FILE: E:\Program Files\apache\htdocs\app\ThinkPHP\Lib\Core\App.class.php  LINE: 122
TRACE
[13-05-07 16:19:05] E:\Program Files\apache\htdocs\app\ThinkPHP\Lib\Core\App.class.php (122) _404(无法加载模块:Form)
[13-05-07 16:19:05] E:\Program Files\apache\htdocs\app\ThinkPHP\Lib\Core\App.class.php (207) App::exec()
[13-05-07 16:19:05] E:\Program Files\apache\htdocs\app\ThinkPHP\Lib\Core\Think.class.php (39) App::run()
[13-05-07 16:19:05] E:\Program Files\apache\htdocs\app\ThinkPHP\Common\runtime.php (242) Think::start()
[13-05-07 16:19:05] E:\Program Files\apache\htdocs\app\ThinkPHP\ThinkPHP.php (30) require(E:\Program Files\apache\htdocs\app\ThinkPHP\Common\runtime.php)
[13-05-07 16:19:05] E:\Program Files\apache\htdocs\app\index.php (5) require(E:\Program Files\apache\htdocs\app\ThinkPHP\ThinkPHP.php)
回复crazyphp2013年05月07日
控制器是这样写的
<?php
class IndexAction extends Action {
public function index(){
$Form = D('Form');
$list = $Form->select();
$this->assign('list',$list);
$this->display();
}
}
?>
回复clx2013年05月14日
ccc
回复clx2013年05月14日
用D方法必须要有对应的类的,你的Model下没form类,查询语句用M方法好些
回复deshaman@126.com2013年06月28日
在Lib目录的Model下面新建一个FormModel.class.php,继承Model类即可。可以在这个类里面写自动验证和自动完成的操作方法。
回复namelesswei2013年11月08日
回复 crazyphp : 这样也行$this->list=$list;
回复namelesswei2013年11月08日
回复 clx : 支持一个!
回复crazyphp2013年05月07日
控制器是这样写的
<?php
class IndexAction extends Action {
public function index(){
$Form = D('Form');
$list = $Form->select();
$this->assign('list',$list);
$this->display();
}
}
?>
回复clx2013年05月14日
ccc
回复clx2013年05月14日
用D方法必须要有对应的类的,你的Model下没form类,查询语句用M方法好些
回复deshaman@126.com2013年06月28日
在Lib目录的Model下面新建一个FormModel.class.php,继承Model类即可。可以在这个类里面写自动验证和自动完成的操作方法。
回复namelesswei2013年11月08日
回复 crazyphp : 这样也行$this->list=$list;
 
crazyphp2013年05月06日
请问我的order用法有错误吗?
public function readAll(){
$Form = D('Form');
$list = $Form->order('create_time desc')->select();
$this->assign('list',$list);
$this->display();
}
 
回复yapph2013年12月16日
$this->list = $list;
 
回复yapph2013年12月16日
$this->list = $list;
祥云网络2013年05月01日
在数据库表有表前缀的情况下,join操作报错Table 'post_cate_re' doesn't exist
mcyami2013年03月27日
求助:查询每个栏目下最新的商品
  1. select * from goods where goods_id in  (select max(goods_id) from goods group by cat_id);
复制代码
 
复制代码
 

这句用tp的连贯操作要怎么写?
回复feyeen2013年06月05日
where($map)->group()............
回复feyeen2013年06月05日
where($map)->group()............
mcyami2013年03月27日
建议group()和having()添加一点实例..
liujiachen2013年11月28日
不知道多表查询方不方便
xieguoen2013年09月03日
Oracle 是没有limit概念的
mxmx2013年08月02日
  1. echo 'Hello,thinkphp...';
复制代码
 
helum2013年06月30日
怎么我看了下好像没有select a from b的形式的,基本的查询语句都是select * from b 这种形式然后再获取a字段内容的,这样子不是耗费查询时间么?
whilelie2013年06月10日
类似于linq方法
crazyphp2013年05月07日
求助
无法加载模块:Form
错误位置
FILE: E:\Program Files\apache\htdocs\app\ThinkPHP\Lib\Core\App.class.php  LINE: 122
TRACE
[13-05-07 16:19:05] E:\Program Files\apache\htdocs\app\ThinkPHP\Lib\Core\App.class.php (122) _404(无法加载模块:Form)
[13-05-07 16:19:05] E:\Program Files\apache\htdocs\app\ThinkPHP\Lib\Core\App.class.php (207) App::exec()
[13-05-07 16:19:05] E:\Program Files\apache\htdocs\app\ThinkPHP\Lib\Core\Think.class.php (39) App::run()
[13-05-07 16:19:05] E:\Program Files\apache\htdocs\app\ThinkPHP\Common\runtime.php (242) Think::start()
[13-05-07 16:19:05] E:\Program Files\apache\htdocs\app\ThinkPHP\ThinkPHP.php (30) require(E:\Program Files\apache\htdocs\app\ThinkPHP\Common\runtime.php)
[13-05-07 16:19:05] E:\Program Files\apache\htdocs\app\index.php (5) require(E:\Program Files\apache\htdocs\app\ThinkPHP\ThinkPHP.php)
crazyphp2013年05月06日
请问我的order用法有错误吗?
public function readAll(){
$Form = D('Form');
$list = $Form->order('create_time desc')->select();
$this->assign('list',$list);
$this->display();
}
祥云网络2013年05月01日
在数据库表有表前缀的情况下,join操作报错Table 'post_cate_re' doesn't exist
mcyami2013年03月27日
求助:查询每个栏目下最新的商品
  1. select * from goods where goods_id in  (select max(goods_id) from goods group by cat_id);
复制代码
 

这句用tp的连贯操作要怎么写?
mcyami2013年03月27日
建议group()和having()添加一点实例..

普通分类: