2016-12-09 5 views
0

単純な1-nの関係(category_idを持つカテゴリとアイテム)を持つ2つのモデルがあります。カテゴリにどれくらいのアイテムがあるかを示したいと思います。私はカウントをキャッシュするのではなく、常にカウントをしたいので、 "total_items_count"というカテゴリテーブルに余分なフィールドがあります。 リレーションが複数の場所(バックエンド、API、フロントエンドなど)から変更される可能性があるため、「countUpdate」関数を呼び出すときに、この合計カウントトリガを最適に行う方法。yii2の2つのモデル間の関係の変化を追跡する方法

私の最初の計画はAFTER_UPDATEイベントを使用することでしたが、アイテムがデータベースに格納された後に(少なくとも新しいアイテムを追加すると) "link()"を呼び出す必要がありました。 。アイテムがあるカテゴリから別のカテゴリに移動する場合は、古いカテゴリも知る必要があります。バックエンドコントローラでは、$ item-> link( 'category'、$ categoryObj)を使用しています。私はこの関係をいつかn-nに変えるかもしれないので。

アイテムとカテゴリ間のリンクが変更された場合の完全な制御方法と、古いリンクカテゴリと新しいリンクカテゴリのカウントの更新についてのアドバイスはありますか? ありがとう

答えて

0

複数の場所からの間違った更新を防止するために、ActiveRecord::updateCounters()メソッドを使用してカテゴリカウントフィールドを更新する必要があることがまず必要です。あなたは次の操作を行うことができ、カテゴリ項目モデルで

:だからあなたはそれらのもののいずれかを行うことができ

public function save($runValidation = true, $attributeNames = null) 
{ 
    if (parent::save(runValidation, attributeNames)) { 
     $this->category->updateCounters(['total_items_count' => 1]); 
     return true; 
    } 
    return false; 
} 

それとも、(カテゴリー\のアプリの\コンポーネントを言わせ)が必要になります集中管理のコンポーネントを書き込むことができますがアプリケーション全体から呼び出します。このコンポーネントにはアイテムを保存するメソッドがあります。例えば:もちろん

public function saveItem($category, $item) 
{ 
    if ($item->save()) { 
     $item->link('category', $category); 
     $category->updateCounters(['total_items_count' => 1]); 
     return true; 
    } 
    return false; 
} 

アイテムを削除すると、あなたは呼び出します。

$category->updateCounters(['total_items_count' => -1]); 

See the ActiveRecord::updateCounters() API

をYii2のドキュメントから:

注:もしyii \ db \ ActiveRecord :: save()を使用してカウンタ列を更新すると、不正確な結果に終わる可能性があります。これはsa私のカウンタは、同じカウンタ値を読み書きする複数の要求によって保存されています。

古いカテゴリを追跡する必要がある場合は、別の列を作成してカテゴリ項目テーブルに「old_category」と言うと、アイテムのカテゴリを変更するとそこに古いカテゴリIDを置きますcategory_id列の新しいカテゴリID。

これは役に立ちますか?ご不明な点がございましたら、お尋ねください!

+0

ありがとう、私は今週テストします。アイテムが更新されたとき(または更新時およびアイテムが作成されたとき)にのみsave()が呼び出されますか? – Dakipro

+0

両方の場合にsave()が呼び出されます。したがって、アイテムを作成しているか更新しているかを確認することができます。アイテムを更新する場合は、total_items_countを更新する必要はありません。また、$ insertパラメータを持つafterSaveメソッドを使用することもできます。これは、アイテムが作成された場合に 'true'になります。その後、parent :: afterSave()を呼び出すことを忘れないでください! –

+0

ありがとう、私は今すぐ近くになっています。これは、アイテムモデルを保存してから、このようにリンクする必要があるため、カテゴリが変更されたかどうかを判断できないということです。 '$ model = $ this-> findModel($ id); if($ model-> load(Yii :: $ app-> request-> post())){ $ model-> save(); //それをリンクしてください $ model-> link( 'category'、$ categoryObj); ' そしてsave()は2回呼び出され、どちらの場合も「カテゴリ」が変更されているかどうかわかりません($ this-> isAttributeChanged( 'category')は常にfalseを返します) – Dakipro

関連する問題