qingmingsang

 模型实例化

在ThinkPHP中,可以无需进行任何模型定义。只有在需要封装单独的业务逻辑的时候,模型类才是必须被定义的。

直接实例化
可以和实例化其他类库一样实例化模型类,例如:
$User = new \Home\Model\UserModel();
$Info = new \Admin\Model\InfoModel();
// 带参数实例化
$New  = new \Home\Model\NewModel(\'blog\',\'think_\',$connection);
模型类通常都是继承系统的\Think\Model类,该类的架构方法有三个参数,分别是:
Model([\'模型名\'],[\'数据表前缀\'],[\'数据库连接信息\']);

模型名 模型的名称 和数据表前缀一起配合用于自动识别数据表名称
数据表前缀 当前数据表前缀 和模型名一起配合用于自动识别数据表名称
数据库连接信息 当前数据表的数据库连接信息 如果没有则获取配置文件中的

如果当前数据表没有前缀,则传入空字符串即可

数据库连接信息参数支持三种格式:

1、字符串定义
字符串定义采用DNS格式定义,格式定义规范为:

type://username:passwd@hostname:port/DbName
// 3.2.1以上版本还可以支持字符集设定
type://username:passwd@hostname:port/DbName#charset

例如:
new \Home\Model\NewModel(\'blog\',\'think_\',\'mysql://root:1234@localhost/demo\');

2、数组定义
可以传入数组格式的数据库连接信息,例如:
$connection = array(    
\'db_type\'    =>   \'mysql\',   
\'db_host\'    =>   \'127.0.0.1\',    
\'db_user\'    =>   \'root\',    
\'db_pwd\'     =>   \'12345\',    
\'db_port\'    =>    3306,    
\'db_name\'    =>    \'demo\',
);
new \Home\Model\NewModel(\'new\',\'think_\',$connection);

3.2.1以上版本还可以支持数据编码设定,例如:
$connection = array(    
\'db_type\'    =>   \'mysql\',    
\'db_host\'    =>   \'127.0.0.1\',    
\'db_user\'    =>   \'root\',    
\'db_pwd\'     =>   \'12345\',    
\'db_port\'    =>    3306,    
\'db_name\'    =>    \'demo\',     
\'db_charset\' =>    \'utf8\',
);
new \Home\Model\NewModel(\'new\',\'think_\',$connection);

3、配置定义
可以事先在配置文件中定义好数据库连接信息,然后在实例化的时候直接传入配置的名称即可,例如:

//数据库配置1
\'DB_CONFIG1\' => array(     
\'db_type\'  => \'mysql\',     
\'db_user\'  => \'root\',     
\'db_pwd\'   => \'1234\',     
\'db_host\'  => \'localhost\',     
\'db_port\'  => \'3306\',     
\'db_name\'  => \'thinkphp\'
),
//数据库配置2
\'DB_CONFIG2\' => \'mysql://root:1234@localhost:3306/thinkphp\',在配置文件中定义数据库连接信息的时候也支持字符串和数组格式,格式和上面实例化传入的参数一样。

然后就可以这样实例化模型类传入连接信息:

new \Home\Model\NewModel(\'new\',\'think_\',\'DB_CONFIG1\');
new \Home\Model\BlogModel(\'blog\',\'think_\',\'DB_CONFIG2\');

事实上,当实例化的时候没有传入任何的数据库连接信息的时候,系统其实默认会获取配置文件中的相关配置参数,包括:
\'DB_TYPE\'      =>  \'\',     // 数据库类型
\'DB_HOST\'      =>  \'\',     // 服务器地址
\'DB_NAME\'      =>  \'\',     // 数据库名
\'DB_USER\'      =>  \'\',     // 用户名
\'DB_PWD\'       =>  \'\',     // 密码
\'DB_PORT\'      =>  \'\',     // 端口
\'DB_PREFIX\'    =>  \'\',     // 数据库表前缀
\'DB_DSN\'       =>  \'\',     // 数据库连接DSN 用于PDO方式
\'DB_CHARSET\'   =>  \'utf8\', // 数据库的编码

默认为utf8如果应用配置文件中有配置上述数据库连接信息的话,实例化模型将会变得非常简单。

 

 

M方法

实例化模型
D方法实例化模型类的时候通常是实例化某个具体的模型类,如果仅仅是对数据表进行基本的CURD操作的话,使用M方法实例化的话,由于不需要加载具体的模型类,所以性能会更高。

例如:
// 使用M方法实例化
$User = M(\'User\');// 和用法 $User = new \Think\Model(\'User\'); 等效
// 执行其他的数据操作
$User->select();

M方法也可以支持跨库操作,例如:
// 使用M方法实例化 操作db_name数据库的ot_user表
$User = M(\'db_name.User\',\'ot_\');
//执行其他的数据操作
$User->select();

M方法的参数和\Think\Model类的参数是一样的,也就是说,也可以这样实例化:
$New  = M(\'new\',\'think_\',$connection);
// 等效于 $New = new \Think\Model(\'new\',\'think_\',$connection);

M方法实例化的时候,默认情况下是直接实例化系统的\Think\Model类,
如果希望实例化其他的公共模型类的话,可以使用如下方法:
$User = M(\'\Home\Model\CommonModel:User\',\'think_\',\'db_config\');
// 相当于 $User = new \Home\Model\CommonModel(\'User\',\'think_\',\'db_config\');
如果模型类有自己的业务逻辑,M方法是无法支持的,就算是已经定义了具体的模型类,M方法实例化的时候是会直接忽略。

实例化空模型类
如果仅仅是使用原生SQL查询的话,不需要使用额外的模型类,实例化一个空模型类即可进行操作了,例如:

//实例化空模型
$Model = new Model();
//或者使用M快捷方法是等效的
$Model = M();
//进行原生的SQL查询
$Model->query(\'SELECT * FROM think_user WHERE status = 1\');实例化空模型类后还可以用table方法切换到具体的数据表进行操作

在实例化的过程中,经常使用D方法和M方法,这两个方法的区别在于M方法实例化模型无需用户为每个数据表定义模型类,如果D方法没有找到定义的模型类,则会自动调用M方法。

D方法
D方法实例化
系统提供了一个快捷方法D用于数据模型的实例化操作。

<?php
//实例化模型
$User = D(\'User\');
// 相当于 $User = new \Home\Model\UserModel();
// 执行具体的数据操作
$User->select();

当 \Home\Model\UserModel 类不存在的时候,D函数会尝试实例化公共模块下面的 \Common\Model\UserModel 类。

D方法的参数就是模型的名称,并且和模型类的大小写定义是一致的,例如:
参数          实例化的模型文件(假设当前模块为Home)
User          对应的模型类文件的 \Home\Model\UserModel.class.php
UserType      对应的模型类文件的 \Home\Model\UserTypeModel.class.php

在Linux环境下面,要注意D方法实例化的时候的模型名称的大小写。

D方法可以自动检测模型类,如果存在自定义的模型类,则实例化自定义模型类,如果不存在,则会实例化系统的\Think\Model基类,同时对于已实例化过的模型,不会重复去实例化。

D方法还可以支持跨模块调用,需要使用:
//实例化Admin模块的User模型
D(\'Admin/User\');//实例化Extend扩展命名空间下的Info模型
D(\'Extend://Editor/Info\');
注意:跨模块实例化模型类的时候 不支持自动加载公共模块的模型类。

table方法
table方法属于模型类的连贯操作方法之一,主要用于指定操作的数据表。

一般情况下,操作模型的时候系统能够自动识别当前对应的数据表,所以,使用table方法的情况通常是为了:

切换操作的数据表;
对多表进行操作;

例如:
$Model->table(\'think_user\')->where(\'status>1\')->select();
也可以在table方法中指定数据库,例如:
$Model->table(\'db_name.think_user\')->where(\'status>1\')->select();table方法指定的数据表需要完整的表名,但可以采用下面的方式简化数据表前缀的传入,例如:
$Model->table(\'__USER__\')->where(\'status>1\')->select();
会自动获取当前模型对应的数据表前缀来生成 think_user 数据表名称。

需要注意的是table方法不会改变数据库的连接,所以你要确保当前连接的用户有权限操作相应的数据库和数据表。切换数据表后,系统会自动重新获取切换后的数据表的字段缓存信息。

如果需要对多表进行操作,可以这样使用:
$Model->field(\'user.name,role.title\')->table(\'think_user user,think_role role\')->limit(10)->select();
为了尽量避免和mysql的关键字冲突,可以建议使用数组方式定义,例如:
$Model->field(\'user.name,role.title\')->table(array(\'think_user\'=>\'user\',\'think_role\'=>\'role\'))->limit(10)->select();使用数组方式定义的优势是可以避免因为表名和关键字冲突而出错的情况。一般情况下,无需调用table方法,默认会自动获取当前模型对应或者定义的数据表。

 

add
#数据写入
$User = M("User"); // 实例化User对象
$data[\'name\'] = \'ThinkPHP\';
$data[\'email\'] = \'ThinkPHP@gmail.com\';
$User->add($data);

或者使用data方法连贯操作
$User = M("User"); // 实例化User对象
$User->data($data)->add();如果在add之前已经创建数据对象的话(例如使用了create或者data方法),add方法就不需要再传入数据了。

使用create方法的例子:
$User = M("User"); // 实例化User对象
// 根据表单提交的POST数据创建数据对象
if($User->create()){    
    $result = $User->add(); // 写入数据到数据库     
    if($result){        
        // 如果主键是自动增长型 成功后返回值就是最新插入的值       
        $insertId = $result;    
    }
}
create方法并不算是连贯操作,因为其返回值可能是布尔值,所以必须要进行严格判断。

在执行add方法之前,我们可以调用相关的连贯操作方法,配合完成数据写入操作。

#字段过滤
如果写入了数据表中不存在的字段数据,则会被直接过滤,例如:

$data[\'name\'] = \'thinkphp\';
$data[\'email\'] = \'thinkphp@gmail.com\';
$data[\'test\'] = \'test\';
$User = M(\'User\');
$User->data($data)->add();
其中test字段是不存在的,所以写入数据的时候会自动过滤掉。

在3.2.2版本以上,如果开启调试模式的话,则会抛出异常,提示:非法数据对象:[test=>test]

如果在add方法之前调用field方法,则表示只允许写入指定的字段数据,其他非法字段将会被过滤,例如:
$data[\'name\'] = \'thinkphp\';
$data[\'email\'] = \'thinkphp@gmail.com\';
$data[\'test\'] = \'test\';
$User = M(\'User\');
$User->field(\'name\')->data($data)->add();最终只有name字段的数据被允许写入,email和test字段直接被过滤了,哪怕email也是数据表中的合法字段。

#字段内容过滤
通过filter方法可以对数据的值进行过滤处理,例如:
$data[\'name\'] = \'<b>thinkphp</b>\';
$data[\'email\'] = \'thinkphp@gmail.com\';
$User = M(\'User\');
$User->data($data)->filter(\'strip_tags\')->add();
写入数据库的时候会把name字段的值转化为thinkphp。

#Mysql的特殊操作
如果是mysql数据库的话,系统还提供了针对Mysql的操作方法,包括批量插入数据和替换操作,如:
// 批量添加数据
$dataList[] = array(\'name\'=>\'thinkphp\',\'email\'=>\'thinkphp@gamil.com\');
$dataList[] = array(\'name\'=>\'onethink\',\'email\'=>\'onethink@gamil.com\');
$User->addAll($dataList);

同时在数据插入时允许更新操作:
add($data=\'\',$options=array(),$replace=false)
其中add方法增加$replace参数(是否添加数据时允许覆盖),true表示覆盖,默认为false

delete

#删除数据
$Form = M(\'Form\');
$Form->delete(5);
表示删除主键为5的数据,
delete方法可以删除单个数据,也可以删除多个数据,这取决于删除条件,例如:
$User = M("User"); // 实例化User对象
$User->where(\'id=5\')->delete(); // 删除id为5的用户数据
$User->delete(\'1,2,5\'); // 删除主键为1,2和5的用户数据
$User->where(\'status=0\')->delete(); // 删除所有状态为0的用户数据
delete方法的返回值是删除的记录数,如果返回值是false则表示SQL出错,返回值如果为0表示没有删除任何数据。

也可以用order和limit方法来限制要删除的个数,例如:
// 删除所有状态为0的5 个用户数据 按照创建时间排序
$User->where(\'status=0\')->order(\'create_time\')->limit(\'5\')->delete();

为了避免错删数据,如果没有传入任何条件进行删除操作的话,不会执行删除操作,例如:
$User = M("User"); // 实例化User对象
$User->delete();
不会删除任何数据,
如果你确实要删除所有的记录,除非使用下面的方式:
$User = M("User"); // 实例化User对象
$User->where(\'1\')->delete();

#更新数据

save

$User = M("User"); // 实例化User对象
// 要修改的数据对象属性赋值
$data[\'name\'] = \'ThinkPHP\';
$data[\'email\'] = \'ThinkPHP@gmail.com\';
$User->where(\'id=5\')->save($data); // 根据条件更新记录

也可以改成对象方式来操作:
$User = M("User"); // 实例化User对象
// 要修改的数据对象属性赋值
$User->name = \'ThinkPHP\';
$User->email = \'ThinkPHP@gmail.com\';
$User->where(\'id=5\')->save(); // 根据条件更新记录
数据对象赋值的方式,save方法无需传入数据,会自动识别。

注意:save方法的返回值是影响的记录数,如果返回false则表示更新出错,因此一定要用恒等来判断是否更新失败。

为了保证数据库的安全,避免出错更新整个数据表,如果没有任何更新条件,数据对象本身也不包含主键字段的话,save方法不会更新任何数据库的记录。

因此下面的代码不会更改数据库的任何记录
$User->save($data);
除非使用下面的方式:
$User = M("User"); // 实例化User对象
// 要修改的数据对象属性赋值
$data[\'id\'] = 5;
$data[\'name\'] = \'ThinkPHP\';
$data[\'email\'] = \'ThinkPHP@gmail.com\';
$User->save($data); // 根据条件保存修改的数据
如果id是数据表的主键的话,系统自动会把主键的值作为更新条件来更新其他字段的值。

#字段和数据过滤
和add方法一样,save方法支持使用field方法过滤字段和filter方法过滤数据,例如:
$User = M("User"); // 实例化User对象
// 要修改的数据对象属性赋值
$data[\'name\'] = \'test\';
$data[\'email\'] = \'<b>test@gmail.com</b>\';
$User->where(\'id=5\')->field(\'email\')->filter(\'strip_tags\')->save($data); // 根据条件保存修改的数据
当使用field(\'email\')的时候,
只允许更新email字段的值(采用strip_tags方法过滤),name字段的值将不会被修改。

还有一种方法是通过create或者data方法创建要更新的数据对象,然后进行保存操作,这样save方法的参数可以不需要传入。
$User = M("User"); // 实例化User对象
// 要修改的数据对象属性赋值
$data[\'name\'] = \'ThinkPHP\';
$data[\'email\'] = \'ThinkPHP@gmail.com\';
$User->where(\'id=5\')->data($data)->save(); // 根据条件保存修改的数据

使用create方法的例子:
$User = M("User"); // 实例化User对象
//根据表单提交的POST数据创建数据对象
$User->create();
$User->save(); // 根据条件保存修改的数据

#更新字段
setField
如果只是更新个别字段的值,可以使用setField方法。
使用示例:
$User = M("User"); // 实例化User对象
// 更改用户的name值
$User-> where(\'id=5\')->setField(\'name\',\'ThinkPHP\');

setField方法支持同时更新多个字段,只需要传入数组即可,例如:
$User = M("User"); // 实例化User对象
// 更改用户的name和email的值
$data = array(\'name\'=>\'ThinkPHP\',\'email\'=>\'ThinkPHP@gmail.com\');
$User-> where(\'id=5\')->setField($data);

setInc、setDec
而对于统计字段(通常指的是数字类型)的更新,系统还提供了setInc和setDec方法。
$User = M("User"); // 实例化User对象
$User->where(\'id=5\')->setInc(\'score\',3); // 用户的积分加3
$User->where(\'id=5\')->setInc(\'score\'); // 用户的积分加1
$User->where(\'id=5\')->setDec(\'score\',5); // 用户的积分减5
$User->where(\'id=5\')->setDec(\'score\'); // 用户的积分减1

 


#读取数据

find
读取数据是指读取数据表中的一行数据(或者关联数据),主要通过find方法完成,例如:

$User = M("User"); // 实例化User对象
// 查找status值为1name值为think的用户数据
$data = $User->where(\'status=1 AND name="thinkphp"\')->find();
dump($data);

如果查询出错,find方法返回false,如果查询结果为空返回NULL,查询成功则返回一个关联数组(键值是字段名或者别名)。
 
如果上面的查询成功的话,会输出:
array (size=3)  
\'name\' => string \'thinkphp\' (length=8)
\'email\' => string \'thinkphp@gmail.com\' (length=18)
\'status\'=> int 1
即使满足条件的数据不止一个,find方法也只会返回第一条记录(可以通过order方法排序后查询)。

还可以用data方法获取查询后的数据对象(查询成功后)
$User = M("User"); // 实例化User对象
// 查找status值为1name值为think的用户数据
$User->where(\'status=1 AND name="thinkphp"\')->find();
dump($User->data());

#读取数据集

select
读取数据集其实就是获取数据表中的多行记录(以及关联数据),使用select方法,使用示例:
$User = M("User"); // 实例化User对象
// 查找status值为1的用户数据 以创建时间排序 返回10条数据$list = $User->where(\'status=1\')->order(\'create_time\')->limit(10)->select();
如果查询出错,select的返回值是false,如果查询结果为空,则返回NULL,否则返回二维数组。

#读取字段值

getField
读取字段值其实就是获取数据表中的某个列的多个或者单个数据,最常用的方法是 getField方法。

示例如下:
$User = M("User"); // 实例化User对象
// 获取ID为3的用户的昵称
$nickname = $User->where(\'id=3\')->getField(\'nickname\');默认情况下,当只有一个字段的时候,返回满足条件的数据表中的该字段的第一行的值。

如果需要返回整个列的数据,可以用:
$User->getField(\'id\',true); // 获取id数组
//返回数据格式如array(1,2,3,4,5)一维数组,其中value就是id列的每行的值

如果传入多个字段的话,默认返回一个关联数组:
$User = M("User"); // 实例化User对象
// 获取所有用户的ID和昵称列表
$list = $User->getField(\'id,nickname\');
//两个字段的情况下返回的是array(`id`=>`nickname`)的关联数组,以id的值为key,nickname字段值为value
这样返回的list是一个数组,键名是用户的id字段的值,键值是用户的昵称nickname。

如果传入多个字段的名称,例如:
$list = $User->getField(\'id,nickname,email\');//返回的数组格式是array(`id`=>array(`id`=>value,`nickname`=>value,`email`=>value))是一个二维数组,key还是id字段的值,但value是整行的array数组,类似于select()方法的结果遍历将id的值设为数组key
返回的是一个二维数组,类似select方法的返回结果,区别的是这个二维数组的键名是用户的id(准确的说是getField方法的第一个字段名)。

如果我们传入一个字符串分隔符:
$list = $User->getField(\'id,nickname,email\',\':\');
那么返回的结果就是一个数组,键名是用户id,键值是 nickname:email的输出字符串。

getField方法还可以支持限制数量,例如:
$this->getField(\'id,name\',5); // 限制返回5条记录
$this->getField(\'id\',3); // 获取id数组 限制3条记录

 

-----

 

where

where方法可以完成包括普通查询、表达式查询、快捷查询、区间查询、组合查询在内的查询操作。
where方法的参数支持字符串和数组,虽然也可以使用对象但并不建议。

#字符串条件
使用字符串条件直接查询和操作,例如:
$User = M("User"); // 实例化User对象
$User->where(\'type=1 AND status=1\')->select();
最后生成的SQL语句是
SELECT * FROM think_user WHERE type=1 AND status=1

如果使用3.1以上版本的话,使用字符串条件的时候,应该配合预处理机制,确保更加安全,例如:
$Model->where("id=%d and username=\'%s\' and xx=\'%f\'",array($id,$username,$xx))->select();
或者使用:
$Model->where("id=%d and username=\'%s\' and xx=\'%f\'",$id,$username,$xx)->select();如果$id变量来自用户提交或者URL地址的话,如果传入的是非数字类型,则会强制格式化为数字格式后进行查询操作。

 


%d整型输出,%ld长整型输出,
%o以八进制数形式输出整数,
%x以十六进制数形式输出整数,
%u以十进制数输出unsigned型数据(无符号数)。
%c用来输出一个字符,
%s用来输出一个字符串,
%f用来输出实数,以小数形式输出,
%e以指数形式输出实数,
%g根据大小自动选f格式或e格式,且不输出无意义的零。


#数组条件

普通查询
$User = M("User"); // 实例化User对象
$map[\'name\'] = \'thinkphp\';
$map[\'status\'] = 1;// 把查询条件传入查询方法
$User->where($map)->select();
最后生成的SQL语句是
SELECT * FROM think_user WHERE `name`=\'thinkphp\' AND status=1

#表达式查询
上面的查询条件仅仅是一个简单的相等判断,可以使用查询表达式支持更多的SQL查询语法,查询表达式的使用格式:
$map[\'字段1\']  = array(\'表达式\',\'查询条件1\');
$map[\'字段2\']  = array(\'表达式\',\'查询条件2\');
$Model->where($map)->select(); //也支持
表达式不分大小写,支持的查询表达式有下面几种,分别表示的含义是:

表达式                             含义
EQ                              等于(=)
NEQ                            不等于(<>)
GT                                大于(>)
EGT                             大于等于(>=)
LT                                 小于(<)
ELT                              小于等于(<=)
LIKE                             模糊查询
[NOT] BETWEEN            (不在)区间查询
[NOT] IN                       (不在)IN 查询
EXP                               表达式查询,支持SQL语法

#多次调用
3.1.3版本开始,where方法支持多次调用,但字符串条件只能出现一次,例如:

$map[\'a\'] = array(\'gt\',1);
$where[\'b\'] = 1;
$Model->where($map)->where($where)->where(\'status=1\')->select();多次的数组条件表达式会最终合并,但字符串条件则只支持一次。

 

field

field主要用于查询

#指定字段
$Model->field(\'id,title,content\')->select();
这里使用field方法指定了查询的结果集中包含id,title,content三个字段的值。
执行的SQL相当于:
SELECT id,title,content FROM table

可以给某个字段设置别名,例如:
$Model->field(\'id,nickname as name\')->select();
执行的SQL语句相当于:
SELECT id,nickname as name FROM table

#使用SQL函数
可以在field方法中直接使用函数,例如:
$Model->field(\'id,SUM(score)\')->select();
执行的SQL相当于:
SELECT id,SUM(score) FROM table

#使用数组参数
field方法的参数可以支持数组,例如:
$Model->field(array(\'id\',\'title\',\'content\'))->select();
最终执行的SQL和前面用字符串方式是等效的。

数组方式的定义可以为某些字段定义别名,例如:
$Model->field(array(\'id\',\'nickname\'=>\'name\'))->select();
执行的SQL相当于:
SELECT id,nickname as name FROM table

对于一些更复杂的字段要求,数组的优势则更加明显,例如:
$Model->field(array(\'id\',\'concat(name,\'-\',id)\'=>\'truename\',\'LEFT(title,7)\'=>\'sub_title\'))->select();
执行的SQL相当于:
SELECT id,concat(name,\'-\',id) as truename,LEFT(title,7) as sub_title FROM table

#获取所有字段
如果有一个表有非常多的字段,需要获取所有的字段(这个也许很简单,因为不调用field方法或者直接使用空的field方法都能做到):
$Model->select();
$Model->field()->select();
$Model->field(\'*\')->select();
上面三个用法是等效的,都相当于执行SQL:
SELECT * FROM table
但是这并不是我说的获取所有字段,我希望显式的调用所有字段(对于对性能要求比较高的系统,这个要求并不过分,起码是一个比较好的习惯),那么OK,仍然很简单,下面的用法可以完成预期的作用:
$Model->field(true)->select();
field(true)的用法会显式的获取数据表的所有字段列表,哪怕你的数据表有100个字段。

#字段排除
如果我希望获取排除数据表中的content字段(文本字段的值非常耗内存)之外的所有字段值,我们就可以使用field方法的排除功能,例如下面的方式就可以实现所说的功能:

$Model->field(\'content\',true)->select();
则表示获取除了content之外的所有字段,要排除更多的字段也可以:

$Model->field(\'user_id,content\',true)->select();
//或者用
$Model->field(array(\'user_id\',\'content\'),true)->select();

#用于写入
除了查询操作之外,field方法还有一个非常重要的安全功能--字段合法性检测。
field方法结合create方法使用就可以完成表单提交的字段合法性检测,如果我们在表单提交的处理方法中使用了:
$Model->field(\'title,email,content\')->create();
即表示表单中的合法字段只有title,email和content字段,
无论用户通过什么手段更改或者添加了浏览器的提交字段,都会直接屏蔽。
因为,其他是所有字段我们都不希望由用户提交来决定,你可以通过自动完成功能定义额外的字段写入。

DISTINCT

DISTINCT 方法用于返回唯一不同的值(去重)。

$Model->distinct(true)->field(\'name\')->select();
distinct方法的参数是一个布尔值
生成的SQL语句是:
SELECT DISTINCT name FROM think_user

 

order

$Model->where(\'status=1\')->order(\'id desc\')->limit(5)->select();注意:连贯操作方法没有顺序,可以在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();

 

group

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

例如,我们都查询结果按照用户id进行分组统计:
$this->field(\'username,max(score)\')->group(\'user_id\')->select();
生成的SQL语句是:
SELECT username,max(score) FROM think_score GROUP BY user_id

也支持对多个字段进行分组,例如:
$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

 

limit

#限制结果数量
例如获取满足要求的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\'));

#分页查询
用于文章分页查询是limit方法比较常用的场合,例如:
$Article = M(\'Article\');
$Article->limit(\'10,25\')->select();表示查询文章数据,从第10行开始的25条数据(可能还取决于where条件和order排序的影响 这个暂且不提)。

在3.1版本后,你也可以这样使用:
$Article = M(\'Article\');
$Article->limit(10,25)->select();对于大数据表,尽量使用limit限制查询结果,否则会导致很大的内存开销和性能问题。
 

 

原生的SQL查询和执行操作支持

1、query方法
query方法用于执行SQL查询操作,如果数据非法或者查询错误则返回false,否则返回查询结果数据集(同select方法)。

$Model = new Model() // 实例化一个model对象 没有对应任何数据表
$Model->query("select * from think_user where status=1");

如果当前采用了分布式数据库,并且设置了读写分离的话,query方法始终是在读服务器执行,因此query方法对应的都是读操作,而不管SQL语句是什么。

可以在query方法中使用表名的简化写法,便于动态更改表前缀,例如:

$Model = new Model() // 实例化一个model对象 没有对应任何数据表
$Model->query("select * from __PREFIX__user where status=1");
// 3.2.2版本以上还可以直接使用
$Model->query("select * from __USER__ where status=1");
和上面的写法等效,会自动读取当前设置的表前缀。

2、execute方法
execute用于更新和写入数据的sql操作,如果数据非法或者查询错误则返回false ,否则返回影响的记录数。

$Model = new Model() // 实例化一个model对象 没有对应任何数据表
$Model->execute("update think_user set name=\'thinkPHP\' where status=1");

如果当前采用了分布式数据库,并且设置了读写分离的话,execute方法始终是在写服务器执行,因此execute方法对应的都是写操作,而不管SQL语句是什么。

也可以在execute方法中使用表名的简化写法,便于动态更改表前缀,例如:
$Model = new Model() // 实例化一个model对象 没有对应任何数据表
$Model->execute("update __PREFIX__user set name=\'thinkPHP\' where status=1");// 3.2.2版本以上还可以直接使用
$Model->execute("update __USER__ set name=\'thinkPHP\' where status=1");
和上面的写法等效,会自动读取当前设置的表前缀。

 

统计查询

方法                     说明
Count            统计数量,参数是要统计的字段名(可选)
Max              获取最大值,参数是要统计的字段名(必须)
Min              获取最小值,参数是要统计的字段名(必须)
Avg              获取平均值,参数是要统计的字段名(必须)
Sum               获取总分,参数是要统计的字段名(必须)

用法示例:

$User = M("User"); // 实例化User对象
获取用户数:
$userCount = $User->count();

或者根据字段统计:
$userCount = $User->count("id");

获取用户的最大积分:
$maxScore = $User->max(\'score\');

获取积分大于0的用户的最小积分:
$minScore = $User->where(\'score>0\')->min(\'score\');

获取用户的平均积分:
$avgScore = $User->avg(\'score\');

统计用户的总成绩:
$sumScore = $User->sum(\'score\');

并且所有的统计查询均支持连贯操作的使用。

分类:

技术点:

相关文章:

  • 2022-12-23
  • 2021-06-08
  • 2021-10-14
  • 2022-01-08
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-04-21
  • 2021-10-31
  • 2021-09-10
  • 2021-06-02
  • 2022-12-23
  • 2021-09-04
  • 2021-09-20
相关资源
相似解决方案