laravel的hasOne,hasMany,belongsTo,belongsToMany,hasOneThrough,hasManyThrough详解

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()的写法

 

你可能感兴趣的:(laravel的hasOne,hasMany,belongsTo,belongsToMany,hasOneThrough,hasManyThrough详解)