Php Yii2多个表的联接关系

Php Yii2多个表的联接关系,php,mysql,join,yii2,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

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

您可以使用
多对多关系的语法来避免为连接表声明模型。然后,您的代码将只包含三个模型(
类别
新闻
标签
),并且一切都将更加简单

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']);
    }
}
您可以在和函数中使用这些关系(连接表中的行将由Yii在backround中管理)。但请记住,您应该使用
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()
或任何其他方式(但不是在
链接
取消链接
函数中)

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

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