在使用ThinkPHP5的过程中,我经常使用db进行数据库操作的,后来接触到了模型(model),刚使用时感觉跟db没啥区别,后来查官网知道模型基类中还提供了较多的其他的方法可以方便使用例如获取器、修改器、数据完成等等功能。因此模型的功能更为强大,tp5官网推荐使用model。
就数据格式而言,在DB中是采用的数组格式使用。而在模型中统一使用对象。其中数据库交互后涉及到格式转换。因此在同等情况下db的数据略快与模型方式。因此对于ThinkPHP5使用DB与model的方式具体在编程中选择哪一个按照个人的观点并无强制要求。有时候为了项目中的封装采用模型方式可能更为合适一些
1、模型定义
在model定义一个Blog模型类:
<?php namespace app\demo\model; use think\Model; class Blog extends Model { //默认主键为自动识别,如果需要指定,可以设置属性: //protected $pk = 'uid'; }
模型会自动对应数据表,模型类的命名规则是除去表前缀的数据表名称,采用驼峰法命名,并且首字母大写,例如:
模型名 | 约定对应数据表(假设数据库的前缀定义是 think_) |
---|---|
User | think_user |
UserType | think_user_type |
假设我这个类名和表名不相干的,但我这个类想操作这个表,tp5还有另一种方法:
<?php namespace app\demo\model; use think\Model; class Test extends Model { //设置数据表(不含前缀) protected $name = 'blog'; //设置完整的数据表 // protected $table = 'tp_codes'; }
2、模型调用
模型类可以使用静态调用或者实例化调用两种方式,例如:
//静态调用 $blog = Blog::get(1);//以id为1作为条件(自动根据主键来查) // 实例化模型 $blog = new Blog(); // 使用 Loader 类实例化(单例) $blog = Loader::model('Blog'); // 或者使用助手函数`model` $blog = model('Blog');
3、使用模型增删查改
(1)模型查询操作
//查询 $blog = Blog::get(2);//以id为1作为条件(自动根据主键来查) echo $blog->title;//输出:php实战 $user = new User(); // 查询单个数据 $user->where('name', 'thinkphp') ->find(); //多条件查询,可以传入数组作为查询条件 $bolg = Blog::get(['title'=>'模型1','content'=>'模型内容2']); $bolg = Blog::where(['title'=>'模型1','content'=>'模型内容2'])->find(); echo $bolg->id; //查询全部 $bolg = Blog::all(); foreach($bolg as $key=>$v){ echo $v->title."<br>"; } $user = new User(); // 查询数据集 $user->where('name', 'thinkphp') ->limit(10) ->order('id', 'desc') ->select();
动态查询:通过getByxxx()进行条件查询,后面的xxx是字段名称(按驼峰命名)
//根据某个条件查询数据 getByxxx() 方法 $bolg = Blog::getByTitle('模型1'); echo $bolg->content;
(2)模型添加操作
$blog = new Blog() //添加单条 $blog->title = '模型'; $blog->author = 'lhs'; $blog->publish_time = '11'; $blog->content = '模型内容'; $blog->save(); //批量新增 $list = [ ['title'=>'模型1','author'=>'lhs','publish_time'=>'12','content'=>'模型内容2'], ['title'=>'模型2','author'=>'lhs','publish_time'=>'13','content'=>'模型内容3'] ]; if($blog->saveAll($list)){ echo '用户添加成功!'; }
或者使用isUpdate进行添加操作
//用这个方法添加数据 $blog = Blog::get(1); $blog->title = 'get添加模型'; $blog->author = 'lhs'; $blog->publish_time = '1568908800'; $blog->content = '模型内容'; $blog->id = null; if($blog->isUpdate(false)->save()){ echo "添加成功!"; }
注:要把id设置为空,不然报主键重复的错误
(3)模型更新操作
//更新 $blog = new Blog(); $blog->id = 24; $blog->title = '更新模型'; $blog->author = 'lhs'; $blog->publish_time = '1572919302'; $blog->content = '模型内容'; $blog->isUpdate()->save(); //调用这个方法,isUpdate改true(即默认是更新操作) $blog = Blog::get(1); $blog->title = '更新模型'; $blog->author = 'lhs'; $blog->publish_time = '1553011200'; $blog->content = '模型内容'; if($blog->save()){ echo "更新成功!"; }
(4)模型删除操作
$bolg = Blog::get(25); $bolg->delete(); Blog::destroy(26);
4、读取器和修改器
读取器的作用是在获取数据的字段值后自动进行处理,修改器的作用是可以在数据赋值的时候自动进行转换处理,例如:
<?php namespace app\demo\model; use think\Model; class Codes extends Model { //读取器 public function getPublishTimeAttr($value) { return date("Y-m-d H:i",$value); } //$data为获取整个对象 public function getNameAttr($value,$data) { return '书名:'.$data['name'].',价格:'.$data['price']; } //修改器 public function setPublishTimeAttr($value) { return strtotime($value); } }
使用读取器和修改器
public function read(){ //读取器的方法命名规范:get+属性名(驼峰命名法)+Attr /*$code = Codes::get(1); echo $code->publish_time; //如果自定义了getXXXAttr就调用,没有自定义就原样输出 echo $code->name;*/ //添加 $code = new Codes(); $code->name = '支付宝基金'; $code->category = '经济'; $code->price = '161'; $code->publish_time = '2019-9-27';//调用setPublishTimeAttr方法,在添加是自动转为时间戳 $code->save(); }
5、类型转换
integer:设置为integer(整型)后,该字段写入和输出的时候都会自动转换为整型。
float:该字段的值写入和输出的时候自动转换为浮点型。
boolean:该字段的值写入和输出的时候自动转换为布尔型。
array:如果设置为强制转换为
array
类型,系统会自动把数组编码为json格式字符串写入数据库,取出来的时候会自动解码。
object:该字段的值在写入的时候会自动编码为json字符串,输出的时候会自动转换为
stdclass
对象。
serialize:指定为序列化类型的话,数据会自动序列化写入,并且在读取的时候自动反序列化。
json:
指定为json
类型的话,数据会自动json_encode
写入,并且在读取的时候自动json_decode
处理。
timestamp:指定为时间戳字段类型的话,该字段的值在写入时候会自动使用
strtotime
生成对应的时间戳,输出的时候会自动转换为dateFormat
属性定义的时间字符串格式,默认的格式为Y-m-d H:i:s
例子:
//类型转换 protected $type = [ 'publish_time' => 'timestamp:Y-m-d', 'name' => 'serialize'//序列化 ];
在修改数据时自动转换类型
//自动转换,修改 $code = new Codes(); $code->name = ['中国的经济','金融危机','美国的经济霸权']; $code->category = '经济'; $code->price = '132161'; $code->publish_time = '2019-12-27';//调用setPublishTimeAttr方法,在添加是自动转为时间戳 $code->save();
6、自动完成
数据自动完成指在不需要手动赋值的情况下对字段的值进行处理后写入数据库。
系统支持auto
、insert
和update
三个属性,可以分别在写入、新增和更新的时候进行字段的自动完成机制,auto属性自动完成包含新增和更新操作,例如:
//自动完成,更新 protected $update = [ 'category' => '经济' ]; //自动完成,新增 protected $insert = [ 'category' => '经济' ];
自动完成对category更新和添加
//自动完成,更新 $code = Codes::get(4); $code->name = '支付宝的霸权'; $code->save(); //自动完成,新增 $code = new Codes(); $code->name = '中国经济霸权'; $code->price = '270000'; $code->publish_time = '2019-12-27'; $code->save();
以上的自动完成都是对category固定赋值,如果想动态自动完成就结合修改器
//自动完成 protected $update = [ // 'category' => '经济' 'category' ]; public function setNameAttr($value,$data) { return $data['category'] == '经济' ? '国家经济' : '其他'; }
//自动完成配合修改器,更新 $code = Codes::get(4); $code->name = '美国'; $code->publish_time = '2019-12-2'; $code->save();
结果如下:
7、查询范围
可以对模型的查询和写入操作进行封装,例如:
//查询范围 protected function scopeName($query,$a){ $query->where("name",$a); } protected function scopeCategory($query,$a){ $query->where('category',$a); } //全局查询范围,就算不调用也会自动加上 protected static function base($query){ $query->where('id',2); }
就可以进行下面的条件查询:
//查询范围 $code = Codes::scope('name','php实战') ->scope('category','PHP') ->scope(function($query){ $query->order('id','desc'); }) ->all();
运行结果: