18.6 模型
模型是应用程序中用于处理应用程序数据逻辑的部分,通常模型对象负责在数据库中存取度读取数据。模型中定义了一些操作数据库的常用方法。
18.6.1 模型定义
ThinkPHP 5.0的模型是一种对象-关系映射(Object/Relation Mapping, ORM)的封装,并且提供了简洁的ActiveRecord实现。一般来说,每个数据表会和一个“模型”对应。
ORM的基本特性就是表映射到记录,记录映射到对象,字段映射到对象属性。模型是一种对象化的操作封装,而不是简单的CURD操作。简单的CURD操作直接使用前面提过的Db类即可。模型类和Db类的区别主要在于对象的封装,Db类的查询默认返回的是数组(或者集合),而模型类返回的是当前的模型对象实例(或者集合)。模型是比Db类更高级的数据封装,支持模型关联、模型事件。
为了更好地理解,我们首先在数据库创建一个think_user表:
CREATE TABLE `think_user` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`nickname` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '昵称',
`email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱',
`birthday` int(11) UNSIGNED NOT NULL COMMENT '生日',
`status` tinyint(2) NULL DEFAULT 0 COMMENT '状态',
`create_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '注册时间',
`update_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
database.php
我们为think_user表定义一个User模型(位于application/index/model/User.php):
<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
}
大多情况下,我们无须为模型定义任何属性和方法即可完成基本操作。模型会自动对应一个数据表,规范是:
数据库前缀+当前的模型类名(不包含命名空间)
因为模型类命名是驼峰法,所以获取实际的数据表时会自动转换为小写+下划线命名的数据表名称。如果模型命名不符合这一数据表对应规范,可以给当前模型定义单独的数据表。如果当前模型类需要使用不同的数据库连接,可以定义模型的connection属性。
一般来说,一个应用的模型都是公用的,不区分模块,所以不必在每个模块下面定义模型。
18.6.2 基本操作
完成基本的模型定义后,我们就可以进行基本的模型操作了。下面我们来领略下模型对象化操作的魅力,主要内容包含增加数据、查询数据、更新数据和删除数据。
创建一个User控制器并增加add操作方法:
<?php
namespace app\index\controller;
use app\index\model\User as UserModel;
class User
{
public function add()
{
$user = new UserModel;
$user->nickname='test';
$user->email="thinkphp@qq.com";
$user->birthday=strtotime('1977-03-05');
//用户模型的save方法,新增用户
if($user->save()){
return '用户['.$user->nickname.':'.$user->id.']新增成功';
}else{
return $user->getError();
}
}
}
?>
接下来我们访问http://tp5.jingpan.io/index/user/add。如果看到输出“用户[ test:1 ]新增成功”就表示用户模型写入成功了。
也可以使用数组的形式新增数据:
public function add()
{
$user['nickname']='test';
$user['email']='thinkphp@qq.com';
$user['birthday']=strtotime('2015-04-04');
if($result=UserModel::create($user)){
return '用户['.$result->nickname.':'.$result->id.']新增成功';
}else{
return $user->getError();
}
}
也可以直接进行数据的批量新增,给控制器添加如下addList操作方法:
//批量增加
public function addList()
{
$user=new UserModel();
$list=[
['nickname'=>'流年','email'=>'zhanghsan@qq.com','birthday'=>strtotime('1988-01-15')],
['nickname'=>'test2','email'=>'lise@qq.com','birthday'=>strtotime('1990-09-19')],
];
if($user->saveAll($list)){
return '用户批量新增成功';
}else{
return $user->getError();
}
}
这样即可实现批量新增数据。
2.查询数据
模型的get方法用于获取数据表的数据并返回当前的模型对象实例,通常只需要传入主键作为参数,如果没有传入任何值,就表示获取第一条数据。模型的get方法和Db类的find方法返回结果的区别在于,Db类默认返回的只是数组(注意这里说的是默认,其实仍然可以设置为对象),而模型的get方法查询返回的一定是当前的模型对象实例。
接下来添加User模型的查询功能,给User控制器增加如下read操作方法:
public function read($id=''){
echo $id;
$user=UserModel::get($id);
echo $user->nickname.'<br/>';
echo $user->email.'<br/>';
echo date('Y/m/d',$user->birthday).'<br/>';
}
如果不是根据主键查询,可以传入数组作为查询条件,例如:
public function read(){
$user=UserModel::get(['nickname'=>'test']);
echo $user->nickname.'<br/>';
echo $user->email.'<br/>';
echo date('Y/m/d',$user->birthday).'<br/>';
}
更复杂的查询还可以使用闭包和查询构建器来完成,例如:
//根据nickname读取用户数据
public function read(){
$user=UserModel::get(function($query){
$query->where('nickname','流年')->where('id','>',10)->order('id','desc');
});
echo $user->nickname.'<br/>';
echo $user->email.'<br/>';
echo date('Y/m/d',$user->birthday).'<br/>';
}
如果要查询多个数据,可以使用模型的all方法。我们可以在控制器中添加index操作方法,用于获取用户列表:
public function index(){
$list=UserModel::all();
foreach($list as $user){
echo $user->nickname.'<br/>';
echo $user->email.'<br/>';
echo date('Y/m/d',$user->birthday).'<br/>';
}
echo '----------------------<br/>';
}
3.更新数据
我们可以对查询出来的数据进行更新操作,下面添加一个update操作方法:
//更新用户数据
public function update($id){
$user=UserModel::get($id);
$user->nickname='刘晨';
$user->email='liu2lst@gmail.com';
$user->save();
return '更新用户成功';
}
4.删除数据
我们给User控制器添加delete方法,用于删除用户。
public function delete($id){
$user=UserModel::get($id);
if($user){
$user->delete();
return '删除用户成功';
}else{
return '删除的用户不存在';
}
}
同样我们也可以直接使用destroy方法删除模型数据,例如把上面的delete方法改成如下形式:
//删除用户数据
public function delete($id){
$result=UserModel::destroy($id);
if($result){
return '删除用户成功';
}else{
return '删除的用户不存在';
}
}