ThinkPhp 3.2 数据的连贯操作

时间:2021-10-14 20:39:58

ThinkPHP模型基础类提供的连贯操作方法(也有些框架称之为链式操作),可以有效的提高数据存取的代码清晰度和开发效率,并且支持所有的CURD操作。

使用也比较简单, 假如我们现在要查询一个User表的满足状态为1的前10条记录,并希望按照用户的创建时间排序 ,代码如下:

$User->where('status=1')->order('create_time')->limit(10)->select();

这里的whereorderlimit方法就被称之为连贯操作方法,除了select方法必须放到最后一个外(因为select方法并不是连贯操作方法),连贯操作的方法调用顺序没有先后。

常用操作:

        //造模型对象
$nation = D("Nation"); //查询
//$a = $nation->select(); //查所有,返回关联数组
//$a = $nation->select("n001,n002,n003"); //通过主键查
//$a = $nation->find("n002"); //查一条数据
//$a = $nation->table("Info")->select(); //切换表
//$a = $nation->field("name")->select(); //查询指定字段 另:
//$sql = "update nation set name='矮人族' where code='n001'";
//$a = $nation->query($sql); //执行查询
//$a = $nation->execute($sql); //执行其他操作

ALIAS操作:

alias用于设置当前数据表的别名,便于使用其他的连贯操作例如join方法等。

$Model = M('User');
$Model->alias('a')->join('__DEPT__ b ON b.user_id= a.id')->select();

最终生成的sql语句类似于:

SELECT * FROM think_user a INNER JOIN think_dept b ON b.user_id= a.id
$a = $nation->alias('a')->field("b.Code as 'code',b.Name as 'name',a.name as '民族'")->join("Info b on a.Code=b.Nation")->select();

ORDER操作:

$a = $nation->order("code desc")->select(); //排序

  支持对多个字段的排序,例如:

$Model->where('status=1')->order('id desc,status')->limit(5)->select();
如果没有指定desc或者asc排序规则的话,默认为asc。

  如果你的字段和mysql关键字有冲突,那么建议采用数组方式调用,例如:

$Model->where('status=1')->order(array('order','id'=>'desc'))->limit(5)->select();

LIMIT操作和PAGE操作:

$a = $nation->limit(3,3)->select(); //分页
$a = $nation->page(3,3)->select(); //分页

  限制结果数量:

  例如获取满足要求的10个用户,如下调用即可:

$User = M('User');
$User->where('status=1')->field('id,name')->limit(10)->select();

  limit方法也可以用于写操作,例如更新满足要求的3条数据:

$User = M('User');
$User->where('score=100')->limit(3)->save(array('level'=>'A'));

  page方法也是模型的连贯操作方法之一,是完全为分页查询而诞生的一个人性化操作方法。

  如果使用limit方法,我们要查询第一页和第二页(假设我们每页输出10条数据)写法如下:

$Article = M('Article');
$Article->limit('0,10')->select(); // 查询第一页数据
$Article->limit('10,10')->select(); // 查询第二页数据

  如果用page方法来写则简单多了,例如:

$Article = M('Article');
$Article->page(1,10)->select(); // 查询第一页数据
$Article->page(2,10)->select(); // 查询第二页数据

  显而易见的是,使用page方法你不需要计算每个分页数据的起始位置,page方法内部会自动计算。

  page方法还可以和limit方法配合使用,例如:  

$Article->limit(25)->page(3)->select();

GROUP操作和HAVING操作:

$a = $nation->table("Car")->field("Brand,avg(Price)")->group("Brand")->select(); //分组
$a = $nation->table("Car")->field("Brand,avg(Price)")->group("Brand")->having("avg(Price)>50")->select();

 group方法只有一个参数,并且只能使用字符串。

也支持对多个字段进行分组,例如:

$this->field('username,max(score)')->group('user_id,test_time')->select();

  生成的SQL语句是:

SELECT username,max(score) FROM think_score GROUP BY user_id,test_time

DISTINCT方法:

    DISTINCT 方法用于返回唯一不同的值 。

    例如:

$Model->distinct(true)->field('name')->select();

  生成的SQL语句是: SELECT DISTINCT name FROM think_user

distinct方法的参数是一个布尔值.

JOIN方法:  

JOIN方法也是连贯操作方法之一,用于根据两个或多个表中的列之间的关系,从这些表中查询数据。

join通常有下面几种类型,不同类型的join操作会影响返回的数据结果。

  • INNER JOIN: 如果表中有至少一个匹配,则返回行,等同于 JOIN
  • LEFT JOIN: 即使右表中没有匹配,也从左表返回所有的行
  • RIGHT JOIN: 即使左表中没有匹配,也从右表返回所有的行
  • FULL JOIN: 只要其中一个表中存在匹配,就返回行

join方法支持多次调用,但指定的数据表必须是全称,但我们可以这样来定义:

$Model
->join('__WORK__ ON __ARTIST__.id = __WORK__.artist_id')
->join('__CARD__ ON __ARTIST__.card_id = __CARD__.id')
->select();

__WORK____CARD__在最终解析的时候会转换为 think_workthink_card

默认采用INNER JOIN 方式,如果需要用其他的JOIN方式,可以改成

$Model->join('RIGHT JOIN __WORK__ ON __ARTIST__.id = __WORK__.artist_id')->select()

或者使用:

$Model->join('__WORK__ ON __artist__.id = __WORK__.artist_id','RIGHT')->select()

UNION方法:

UNION操作用于合并两个或多个 SELECT 语句的结果集。

$Model->field('name')
->table('think_user_0')
->union('SELECT name FROM think_user_1')
->union('SELECT name FROM think_user_2')
->select();

数组用法:

$Model->field('name')
->table('think_user_0')
->union(array('field'=>'name','table'=>'think_user_1'))
->union(array('field'=>'name','table'=>'think_user_2'))
->select();

或者:

$Model->field('name')
->table('think_user_0')
->union(array('SELECT name FROM think_user_1','SELECT name FROM think_user_2'))
->select();

注意:UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。

COMMENT方法:

COMMENT方法 用于在生成的SQL语句中添加注释内容,例如:

$this->comment('查询考试前十名分数')
->field('username,score')
->limit(10)
->order('score desc')
->select();

最终生成的SQL语句是:

SELECT username,score FROM think_score ORDER BY score desc LIMIT 10 /* 查询考试前十名分数 */

DATA方法:

data方法也是模型类的连贯操作方法之一,用于设置当前要操作的数据对象的值。

写操作:

通常情况下我们都是通过create方法或者赋值的方式生成数据对象,然后写入数据库,例如:

$Model = D('User');
$Model->create();
// 这里略过具体的自动生成和验证判断
$Model->add();

又或者直接对对象赋值,例如:

$Model = M('User');
$Model->name = '流年';
$Model->email = 'thinkphp@qq.com';
$Model->add();

那么data方法则是直接生成要操作的数据对象,例如:

$Model = M('User');
$data['name'] = '流年';
$data['email'] = 'thinkphp@qq.com';
$Model->data($data)->add();

注意:如果我们同时使用create方法和data创建数据对象的话,则最后调用的方法有效。

data方法支持数组、对象和字符串,对象方式如下:

$Model = M('User');
$obj = new \stdClass;
$obj->name = '流年';
$obj->email = 'thinkphp@qq.com';
$Model->data($obj)->add();

字符串方式用法如下:

$Model = M('User');
$data = 'name=流年&email=thinkphp@qq.com';
$Model->data($data)->add();

也可以直接在add方法中传入数据对象来新增数据,例如:

$Model = M('User');
$data['name'] = '流年';
$data['email'] = 'thinkphp@qq.com';
$Model->add($data);

但是这种方式data参数只能使用数组。

当然data方法也可以用于更新数据,例如:

$Model = M('User');
$data['id'] = 8;
$data['name'] = '流年';
$data['email'] = 'thinkphp@qq.com';
$Model->data($data)->save();

当然我们也可以直接这样用:

$Model = M('User');
$data['id'] = 8;
$data['name'] = '流年';
$data['email'] = 'thinkphp@qq.com';
$Model->save($data);

同样,此时data参数只能传入数组。

在调用save方法更新数据的时候 会自动判断当前的数据对象里面是否有主键值存在,如果有的话会自动作为更新条件。也就是说,下面的用法和上面等效:

$Model = M('User');
$data['name'] = '流年';
$data['email'] = 'thinkphp@qq.com';
$Model->data($data)->where('id=8')->save();

读操作:

除了写操作外,data方法还可以用于读取当前的数据对象,例如:

$User = M('User');
$map['name'] = '流年';
$User->where($map)->find();
// 读取当前数据对象
$data = $User->data();