Yii2连接多个表的关系

时间:2016-08-08 18:32:26

标签: php mysql join yii2

我是yii2的新手。我已经阅读了关于sof的文档和一些答案,但我仍然不能在yii2中处理关系。我能够为问题创建原始的mysql查询,但我不知道如何使用yii2关系创建相同的查询。我对via,joinWith和一些关键概念感到困惑。我会尽可能地描述问题。 我有四个模特。

Category, CategoryNews, NewsTags, Tags

category table - cat_id, cat_name
news_category table - nc_id, nc_cat_id, nc_news_id
news_tags table - nt_id, nt_news_id, nt_tag_id
tags table - tag_id, tag_name

我需要的是每个类别的标签模型对象,即每个类别都需要属于该类别的所有新闻标签。请求来自gridview。 生成的关系是:

Category Model:

public function getNewsCategory()
{
    return $this->hasMany(NewsCategory::className(), ['nc_cat_id' => 'cat_id']);
}

NewsCategory Model:

public function getNcNews()
{
    return $this->hasOne(News::className(), ['news_id' => 'nc_news_id']);
}

public function getNcCat()
{
    return $this->hasOne(Category::className(), ['cat_id' => 'nc_cat_id']);
}

NewsTags Model:

public function getNtNews()
{
    return $this->hasOne(News::className(), ['news_id' => 'nt_news_id']);
}

public function getNtTag()
{
    return $this->hasOne(Tags::className(), ['tag_id' => 'nt_tag_id']);
}

News Model:

public function getNewsCategory()
{
    return $this->hasMany(NewsCategory::className(), ['nc_news_id' => 'news_id']);
}

public function getNewsTags()
{
    return $this->hasMany(NewsTags::className(), ['nt_news_id' => 'news_id']);
}

Tags Model:

public function getNewsTags()
{
    return $this->hasMany(NewsTags::className(), ['nt_tag_id' => 'tag_id']);
}

即。每个类别包含多个新闻,每个新闻包含多个标签,我需要与每个类别相关的所有标签。 更确切地说,在gridview上,我需要所有类别和一列显示与这些类别相关的所有标签。 请帮忙!!

1 个答案:

答案 0 :(得分:4)

您可以使用many-to-many Category关系语法来避免为联结表声明模型。那么您的代码将只包含三个模型(NewsTagpublic class Category extends ActiveRecord { public function getNews() { return $this->hasMany(News::className(), ['id' => 'news_id']) ->viaTable('news_category_table', ['category_id' => 'id']); } } public class News extends ActiveRecord { public function getCategories() { return $this->hasMany(Category::className(), ['id' => 'category_id']) ->viaTable('news_category_table', ['news_id' => 'id']); } public function getTags() { return $this->hasMany(Tags::className(), ['id' => 'tag_id']) ->viaTable('news_tags_table', ['news_id' => 'id']); } } public class Tag extends ActiveRecord { public function getNews() { return $this->hasMany(News::className(), ['id' => 'news_id']) ->viaTable('news_tags_table', ['tag_id' => 'id']); } } ),一切都会更加简单。

您对AR模型和关系的代码可能如下所示:

TRUE

您可以在viaTablelink函数中使用这些关系(联结表中的行将由Yii在backround中管理)。但请记住,您应该使用unlink()作为$article = new News(); $tag = new Tag(); $tag->save(); $article->link('tags', $tag); $article->link('caterories', $category); 中的第二个参数来删除联结表中的行:

$tag->link('news', $article);
$category->link('news', $article);

反之亦然

Category

要获取给定类别中的所有标记,您可以在public function getTags() { return Tags::find() ->joinWith(['news', 'news.categories C']) ->where(['C.id' => $this->id]) ->distinct(); } 类中声明以下函数:

$category->tags

这将作为关系查询使用,您可以将其用作$category->getTags()->count()link或任何其他方式(但不能用于unlinkTag函数)。< / p>

P.S。在代码中使用提供的示例首先应该更改名称,因为我使用单数形式表示AR类名称(id)和短符号表示主键和外键(tag_id DataModel.sampleDetails = ["Sample 1","sample 2","sample 3"] 等)。我还建议您在代码和数据库结构中使用这种命名方法。

P.P.S。此示例代码未经过测试,因此请小心:)