【问题标题】:Yii2 join relations for multiple tablesYii2 连接多个表的关系
【发布时间】:2016-08-08 18:32:26
【问题描述】:

我是 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 上,我需要所有类别和一个显示与这些类别相关的所有标签的列。 请帮忙!!

【问题讨论】:

    标签: php mysql join yii2


    【解决方案1】:

    您可以避免为联结表声明模型,对many-to-many 关系使用viaTable 语法。那么您的代码将只包含三个模型(CategoryNewsTag),一切都会变得更加简单。

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

    public 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']);
        }
    }
    

    您可以在linkunlink 函数中使用这些关系(联结表中的行将由 Yii 在后台管理)。但请记住,您应该使用TRUE 作为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() 或任何其他方式(但不能用于linkunlink 函数)。

    附:要在代码中使用提供的示例,您应该首先更改名称,因为我对 AR 类名称 (Tag) 使用单数形式,对主键和外键使用短表示法 (idtag_id 等)。而且我建议您在代码和数据库结构中也使用这种命名方法。

    附言此示例代码未经测试,因此请小心:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-22
      • 1970-01-01
      • 2015-03-22
      • 1970-01-01
      • 2012-06-15
      • 2016-11-10
      • 2021-06-22
      相关资源
      最近更新 更多