hasOne、hasMany、belongsTo这3个的大致中文意思:
hasOne:有一个,加上主谓语应该是 ,A有一个B
hasMany:有很多,A有很多B
belongsTo:属于,A属于B
goods_cate(商品分类表:id,titile),goods(商品表:id,cate_id,name),detail(商品详情表:id,goods_id,price)
一个商品分类下面有多个商品,所以:goods_cate hasMany goods; 一个商品属于一个商品分类,所以:goods belongsTo goods_cate
一个商品只有唯一一条商品详情表,所以:goods hasOne detail; 一条商品详情表只属于一个商品,所以:detail hasOne goods
class goods {//goods表
function category() {
return $this->belongsTo('GoodsCate', 'goods_cate表的col', 'goods表的col');
}
function detail() {//方法名随便起
return $this->hasOne('Detail', 'Detail表的col', ' ');
}
function test1() {//测试上面detail()关系是否奏效
$this->with(['detail' => static function($query){
$query->select('id','good_id','detail_content');//这里的id是detail表的id。goods_id是外键必须被选择。
}])
->('id', '=', 10) //这里的id是goods表的id
->get()->toArray();
}
function test2() {//多表字段的模糊查询
$this->with('detail')->where(
function ($query) use ($keywords) {
$query->whereHas('detail', function ($query_detail) use ($keywords) {
$query_detail->where('content', 'like', '%'.keywords.'%');
}) //查询关联表detail的contnet字段
->orWhere('label' , 'like', '%'.keywords.'%');//查询goods表的label字段
});
}
function test2() {//多表字段的模糊查询
//如果是inner join,这句必须得加
$query->whereHas('detail', function ($query_detail) use ($args) {
$query_detail->whereNotNull('id');
});
$this->with('detail')->where(
function ($query) use ($keywords) {
$query->whereHas('detail', function ($query_detail) use ($keywords) {
$query_detail->where('content', 'like', '%'.keywords.'%');}) //查询关联表detail的contnet字段
->orWhere('label' , 'like', '%'.keywords.'%');//查询goods表的label字段
});
}
function test3($args) {//多表字段的模糊查询和其他查询
//如果是inner join,这句必须得加
$query->whereHas('detail', function ($query_detail) use ($args) {
$query_detail->whereNotNull('id');
});
$query->where('cate_id', '=', 5);
//注意这里为了和cate_id=5那个条件保持并列关系,这里的or得继续用$query1包起来,(cate_id=5) and (admin like '%xx%' or detail.real_name like '%xx%')
没有包$query1的话,查询就会变成这样:cate_id=5 and admin like '%xx%' or detail.real_name like '%xx%',因为and优先级高于or,所以查询就变味了。
$query->where(function ($query1) use ($args) {
$query1->whereHas('detail', function ($query_user) use ($args) {$query_user->where('real_name', 'like', '%'.$args['owner'].'%');})
->orWhere('admin' , 'like', '%'.$args['owner'].'%');
});
}
}
class category {//category表
function goods() {
return $this->hasMany('Goods','','');
}
}
class detail {//detail表
function goods() {
return $this->belongsTo('Goods');
}
}
$user = model('Goods')−>find();
$cate = $user−>category;//注意这里末尾没有()
$detail = $user->profile;//注意这里末尾没有()
============================================================
class Application {
public function server() {
return $this->hasManyThrough(Server::class, RelApplicationToServerCluster::class, 'application_id', 'server_cluster_id', 'id', 'server_cluster_id')
->where('server_info.status', '=', 0);
}
}
class Server {
public function application() {
return $this->belongsToMany(Application::class, 'rel_application_to_server_cluster', 'server_cluster_id', 'application_id', 'server_cluster_id', 'id', 'key5')
->where('application.status', '=', 0);
}
}
============================================================
hasManyThrough
https://blog.csdn.net/wxq4100798/article/details/81050136
假设from表用a代替,中间表用b,目标表用c,则
$this->hasManyThrough('c模型','b模型',
'a表与b表关联,在b表中的外键名', 'b表与c表关联,在c表中的外键名',
'a表与b表关联,在a表中的名字', 'b表与c表关联,在b表中的名字',
);
2张表:
2张表 | model A | model B |
1对1 | hasOne() 举例: |
belongsTo() 举例: |
1对多 | hasMany() 举例: |
belongsTo() 举例: |
3张表(中间b表是映射关系表):
3张表 | model A | model C |
1对1 | hasOneThrough() |
hasOneThrough() |
1对多 | hasOneThrough() |
hasManyThrough() |
多对多 | hasManyThrough() 举例:hasManyThrough( c表,b表, b表对应的a表col,c表col, a表col,b表对应的c表col ) |
belongsToMany() 举例:belongsToMany( a表,b表, c表col,b表对应的a表col, b表对应的c表col,a表col ) |
⚠️注意
1、关联查询
modelA的hasOne()与modelB的belongsTo() (modelA的hasMany()与modelB的belongsTo())
若只有modelA中用到AB的关联关系,只需要保留modelA中的hasOne()即可;
若只有modelB中用到AB的关联关系,只需要保留modelB中的belongsTo()即可;
若modelA和modelB中都用到AB的关联关系,同时保留modelA中的hasOne()和modelB中的belongsTo()
2、关联查询(goods表与detail表的关联查询)
(1)select关联表detail的部分字段
如果with关联查询,默认是查询关联表的所有字段的。如果想要只选择部分关联的表的字段,详见goods模型类的test1()的写法
(2)两表字段的模糊查询
如果对goods表的label字段或者detail表的content字段做模糊搜索,详见goods模型类的test2()和test3()的写法