75142913在线留言
【Laravel实战】理解多对多(morphedByMany)多态关联和实际中的应用结合_PHP技术_网络人

【Laravel实战】理解多对多(morphedByMany)多态关联和实际中的应用结合

Kwok 发表于:2022-04-21 10:21:57 点击:39 评论: 0

一对多、多对多关联,相对于来说还是比较容易的,可能后期由于业务升级,对于多表联查会有更多的需求时,可能就会用到多对多多态关联,中文手册里看到表述并不太清楚,也不容易让人理解,所以这里我以开发中实际遇到的案例做为讲解。

一、数据表结构

多对多多态关联的数据数结果最少应该是与4张表产生了关联,这种情况其实并不罕见,以我的美食网为例:

网站里的文章与菜谱可以共同使用同一个Tag标签,比如,我打开“丝瓜"这个标签时,如查询出与之相关的文章和菜谱:

Laravel实战理解多对多morphedByMany多态关联和实际中的应用结合

其实表结构如下:

1、文章表:

articles
    id - integer
    title - string

文章表ID为主键。

2、菜谱表

recipes
    id - integer
    name - string

菜谱表ID为主键。

3、标签表

tags
    id - integer
    name - string

标签表ID为主键。

4、关联表

tags_maps
    tag_id - integer
    taggable_id - integer
    taggable_type - string

关联表是其几张表链接的桥梁,通过关联表,我可以无限链接其它更多的表,如:博客内容使用标签、视频使用标签、图片使用标签等。

tag_id 标签的ID。

taggable_id 与之产生关系的ID,如文章ID、菜谱ID、视频ID等。

taggable_type 与之产生关系的类名,这个需要与上面的taggable_id配合使用。

现在分别插入一条菜谱与文章的关联信息到关联表里:

INSERT INTO `meishi_tags_maps` (`tag_id`, `taggable_id`, `taggable_type`) VALUES(1, 121, 'article');

INSERT INTO `meishi_tags_maps` (`tag_id`, `taggable_id`, `taggable_type`) VALUES(1, 356, 'recipe');

现在Tag的第一个标签就与文章ID121和菜谱ID356产生了关联。我们现在需要通过Laravel的多对多多态关联的方法将其查询出来。

二、建立模型

1、模型

php artisan make:model Article
php artisan make:model Tag
php artisan make:model Recipe
php artisan make:model TagsMap

 文章与菜谱模型里其主要内容为:

//获取文章TAGs(多对多关联)
public function tags()
{
    //与Tag标签表关联
    return $this->morphToMany(Tag::class, 'taggable', 'tags_maps') //关系名(类别字段名将以_type格式)中间表tags_maps,关联ID,关系键tag_id
        ->select('id', 'name'); //只需要标签ID,标签名

}

以上方法会生成下面的SQL查询语句:

select `id`, `name`
from `meishi_tags` inner join `meishi_tags_maps` 
on `meishi_tags`.`id` = `meishi_tags_maps`.`tag_id` 
where `meishi_tags_maps`.`taggable_id` = 1000001 and `meishi_tags_maps`.`taggable_type` = article

注意查询语句最后的结尾是article,这个并不会自动变成此值(不做这步时,此值为AppModelsArticle),我们还需要映射模型,打开app/Providers/AppServiceProvider.php 修改内容如下:

//启动APP服务
public function boot()
{
    $this->bootEloquentMorphs();
}
//映射模型
private function bootEloquentMorphs()
{
    Relation::enforceMorphMap([
        'article' => 'AppModelsArticle', //文章模型
        'recipe' => 'AppModelsRecipe', //菜谱模型
    ]);
}

然后控制器里使用下面的方法即可查询出来当前文章的所有标签:

use AppModelsArticle;

$article = Article::find(1);

foreach ($article->tags as $tag) {
    //
}

2、Tag模型

我们通过返回菜谱与文章时,Tag模型如下:

//获取分配给此标签的所有文章。
public function articles()
{
    return $this->morphedByMany(Article::class, 'taggable', 'tags_maps');
}

//获取分配给此标签的所有菜谱。
public function recipes()
{
    return $this->morphedByMany(Recipe::class, 'taggable', 'tags_maps');
}

查询与Tag相关的文章:

Tag::find(1)->articles;

查询与Tag相关的菜谱:

Tag::find(1)->recipes;

最后,注意一个小坑就好了,模型生成的关联类型是以morphedByMany的每个名参数name_type方式,比如上面我的第二个参数为taggable,那么数据表里的字段名就应该是taggable_type与taggable_id。

 

除非注明,网络人的文章均为原创,转载请以链接形式标明本文地址:https://www.55mx.com/post/215
标签:laravel实战多对多关联Kwok最后编辑于:2022-04-21 11:21:14
0
感谢打赏!

《【Laravel实战】理解多对多(morphedByMany)多态关联和实际中的应用结合》的网友评论(0)

本站推荐阅读

热门点击文章