2016-08-08 12 views
1

私はyii2を初めて使用しています。私はドキュメントといくつかの答えをsofで読んだが、まだ私はyii2の関係で作業することはできません。私は問題の生のmysqlクエリを作成することができますが、私はyii2関係を使用して同じクエリを作成する方法を知りません。私はvia、joinWith、いくつかの重要な概念と混同しています。私はできるだけわかりやすいように問題を作ります。 私は4つのモデルを持っています。私は必要なもの複数のテーブルのYii2結合関係

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

ieです。各カテゴリには複数のニュースが含まれており、各ニュースには複数のタグが含まれており、各カテゴリに関連するすべてのタグが必要です。 もっと正確に言えば、私はすべてのカテゴリと、これらのカテゴリに関連するすべてのタグを表示する列が必要です。 助けてください!

答えて

1

あなたはmany-to-many関係のためviaTable構文を使用して、接合テーブルのモデルの宣言を避けることができます。その後、コードには3つのモデル(Category,NewsおよびTag)しか含まれず、すべてがはるかに簡単になります。

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機能で使用することができますこれらの関係(ジャンクション表の行はbackroundの中でのYiiによって管理されます)。しかし、あなたはジャンクションテーブルの行を削除するにはunlink()第二のparamとしてTRUEを使用する必要があることに注意してください:副

$article = new News(); 
$tag = new Tag();  
$tag->save(); 
$article->link('tags', $tag); 
$article->link('caterories', $category); 

ORその逆

$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(); 
} 

これは、リレーションクエリとして動作します、あなたはとして使用することができます210または$category->getTags()->count()または任意の他の方法として(ただしlinkunlink機能で)。

P.S.私は(idtag_idなど)主キーと外部キーのためのARクラス名(Tag)と短い表記法のための単数形を使用するので、あなたのコードで提供された例を使用するには、まず、名前を変更する必要があります。そして、私はあなたのコードとDB構造で、このような命名法を使用することもできますお勧めします。

P.P.S.この例のコードはとても気をつけてテストされませんでした:)

関連する問題