2017-05-18 7 views
1

雄弁なモデル間のネストされた関係からの平均を計算したいと思います。つまり、programsactivitiesstatisticsという3つのテーブルがあります。ネストされた雄弁な関係から平均を得る

programテーブル:

------------- 
| id | name | 
------------- 
| 1 | Foo | 
| 2 | Bar | 
------------- 

activitiesテーブル:

----------------------------------- 
| id | program_id | name   | 
----------------------------------- 
| 1 | 1   | Foo 1   | 
| 2 | 1   | Foo 2   | 
| 3 | 1   | Foo 3   | 
| 4 | 2   | Bar 1   | 
| 5 | 2   | Bar 2   | 
----------------------------------- 

statisticsテーブル:

----------------------------------- 
| id | activity_id | type | score | 
----------------------------------- 
| 1 | 1   | A | 25 | 
| 2 | 1   | B | 20 | 
| 3 | 1   | A | 22 | 
| 4 | 2   | A | 27 | 
| 5 | 2   | B | 24 | 
| 6 | 3   | A | 23 | 
----------------------------------- 
を次のように

単純化のために、私は構造を最小化しようとします

ここで、のprogramの平均値はtypeで、statisticです。何の活動もwhere句を指定せず、プログラムに存在しない場合は常に0またはnull avgを

$program = Program::find(1); 
$avg  = $program->activities->where('statistics.type', 'A')->avg('statistics.value'); 

$:私は、モデル内の関係を定義し、次のコードを試みたが、無駄。

$program->activitiesがアクティビティのセットを返し、$activity-> statisticsも統計セットを返すので、私は関係を正しく定義していることを確信しています。

アイデア?

答えて

2

あなたはこのようwhereHas()を使用することができます。

Statistics::whereHas('activity', function ($q) use($programId) { 
     $q->where('program_id', $programId); 
    }) 
    ->where('type', 'A') 
    ->avg('score'); 

あなたは「統計belongsToの()の活動」である必要がありますactivityの関係を定義していることを確認してください。

+0

ああ、それは実際に動作しているようですが、実際のコードはビュー全体で 'program'ループしているので、私はどこかに置く必要があると思います。ああ、また、プログラム全体の平均を得ることは可能ですか? (これはプログラムIDを指定する必要はありませんが、 'type'を指定することを意味します) – tronic

+0

@tonicこれをコントローラに入れることはできますが、ロジックをモデルに入れ、コントローラから実行してデータを渡してくださいビュー。データ関連のロジックをビューに保持することはひどい考えです。すべてのプログラムの平均を見つけたいのであれば、単純な 'Statistics :: where( 'type'、 'A') - > avg( 'score')'はあなたのために働きませんか?統計情報の中にはプログラムを持たないものがあり、いくつかのアクティビティのみに属する統計情報を取得したい場合は、 'has()'を使います: 'Statistics :: has( 'activity') - > where( 'type'、 'A') - > avg( 'score') ' –

+0

ああ、2番目の質問に気をつけて、私はちょうど' statistics'に直接where節を直接使うことができます。 – tronic