使用模型以及关联模型(ORM)来操作数据库
- 首先在讨论一下模型的定义,ORM是以对象的方式来处理业务逻辑。
- Db 和模型是不分离得。 Db是模型的一个基础,用模型操作数据库其实是下面还是用底层的Db来操作数据库的。
- Db属于数据库的访问层,但模型model是建立在数据库访问层上面的更加抽象的业务层。
不同的是Db返回的是一个数组,但是模型返回的是一个对象。对于数组的操作我们只能使用tp5内置的数组操作方法,但是返回的模型对象里面有很多属性,我们可以更加灵活的操作。
1. 简单的单表查询
- 在model\Banner.php中让Banner类继承于think\Model,那个它就变成了一个模型类。不需要自己写getBannerByID方法来操作数据库了。
- 在controller\Banner.php中
php $banner = BannerModel::get($id);
直接调用tp5封装得get方法就可以。不用关心它是怎么操作数据库的,调用tp5封装的model类的方法就是可以了。
<?php
namespace app\api\model;
use think\Model;
class Banner extends Model{
}
<?php
namespace app\api\controller\v1;
use app\api\model\Banner as BannerModel;
use app\api\validate\IDMustBePositiveInt;
use app\lib\exception\BannerMissException;
class Banner{
public function getBanner($id) {
(new IDMustBePositiveInt())->goCheck();
$banner = BannerModel::get($id);
// $banner = BannerModel::getBannerByID($id);
if (!$banner) {
throw new BannerMissException();
}
return $banner;
}
}
- 获取单个数据的方法包括:get,find.
模型无论使用get还是find方法查询,返回的是都当前模型的对象实例,如果查询数据不存在,则返回Null,除了获取模型数据外,还可以使用模型的方法。- 获取多个数据:all或者select
模型的all方法或者select方法返回的是一个包含多个模型实例的数据集对象(默认为\think\model\Collection)
2. 关联表的查询(一对多)
新建一个BannerItem模型映射数据库中的banneritem表,Banner表和BannerItem是一对多的关系
第一步:定义关联关系。在Banner模型中定义和BannerItem表的关联.
一对多关联的情况也比较常见,使用hasMany方法定义,参数包括:
hasMany(‘关联模型’,‘外键’,‘主键’);
- 除了关联模型外,其它参数都是可选。
- 关联模型(必须):模型名或者模型类名
- 外键:关联模型外键,默认的外键名规则是当前模型名+_id
- 主键:当前模型主键,一般会自动获取也可以指定传入
<?php
namespace app\api\model;
use think\Model;
class Banner extends Model{
public function items(){
return $this->hasMany('BannerItem','banner_id','id');
}
}
第二步:在控制器中调用关联关系。$banner = BannerModel::with('items')->find($id);
<?php
namespace app\api\controller\v1;
use app\api\model\Banner as BannerModel;
use app\api\validate\IDMustBePositiveInt;
use app\lib\exception\BannerMissException;
class Banner{
public function getBanner($id) {
(new IDMustBePositiveInt())->goCheck();
//这个items就是在模型中定义的关联关系
$banner = BannerModel::with('items')->find($id);
if (!$banner) {
throw new BannerMissException();
}
return $banner;
}
}
//如果这一个Banner模型存在多个关联模型,就直接在model\Banner.php中定义多个关联模型,
//然后在控制器中使用的时候,BannerModel::with(['items','..','..'])->find($id);用数组来表示。
返回的结构中就有BannerItem数据表的信息,表现在结果中的items(关联关系名)数组
3. 关联表的查询(嵌套查询)
首先梳理一下嵌套关联数据表
Banner表——>(一对多)——>BannerItem表———>(一对一)———>Image表
新建Image模型,然后在BannerItem模型中定义与Image模型的关联关系:
在Banner模型定义与BannerItem模型的一对多的关联关系:
在控制器中使用
4. 关联表的查询(一对一)
-
belongsTo和hasOne()是不一样的,一对一也存在主从关系。
-
在使用tp5模型的ORM的时候出现belongsTo和hasOne都有表示一对一的关系,但是二者并不相同。以下举例说明两者的区别:
-
首先有user表 字段 id,name,password字段
然后有user_address表 id,user_id ,city字段 -
在User模型中关联user_address表的时候使用hasOne,因为在user表中没有关联两个表的外键。
在UserAddress模型中关联user表的时候使用belongsTo,因为在user_address表中有关联两个表的外键user_id。
总结tp5中的一对一的关联的应用,两个表a,和b是一对一的关系,外键
定义在a表中,那么在a的模型中关联b模型,就要使用belongsTo
。在b模型中关联a模型就要使用hasOne
。
5. 模型的新增
$user = new User;
$user->save([
'name' => 'thinkphp',
'email' => 'thinkphp@qq.com'
]);
---------------------------------
$user = new User([
'name' => 'thinkphp',
'email' => 'thinkphp@qq.com'
]);
$user->save();
//新增一条user记录
private function newUser($openid) {
$user = UserModel::create([
'openid' => $openid
]);
}