2016-02-16 9 views
6

私は写真の代わりに票を、投票表に整数の投票列を持っていることを除いて、in documentationと全く同じ多対多関係を1対多に持っています。そのような:Laravel 5.2多形性関係のクエリスコープ

-votes 
--id 
--vote 
--voteable_id 
--voteable_type 

投票モデルがvoteable方法があります。

public function voteable() 
{ 
    return $this->morphTo(); 
} 

しかし、私は私が持っているVoteableTrait、作成している(この例ではページ)に添付票を持ちたいモデル用

vote()morphManyメソッドとスコープを取得しようとしています。スコープは、特定のモデルに属するすべての投票の合計を加算し、その合計によって親モデルを並べ替えます。私が試したとして、対象範囲:

public function scopeWithVotesTrait($query) 
{ 
    return $query->with(['votes' => function($q){ 
     $q->select(\DB::raw("SUM(vote) AS votes"), 'voteable_id')->first(); 
    }]); 
} 

しかし、これでは私がすることはできませんORDERBY Laravelは、2つの異なるクエリ、親モデル用と投票のための1つを実行して、それはそうです。ページの結果:: withVotesTrait() - >最初は()配列に票を置く:

{ 
"id": 1, 
    "votes": [ 
    { 
     "votes": "-1", 
     "voteable_id": 1 
    } 
    ] 
} 

私が持っていた他のアイデアは、参加の代わりに実行するようにした - を>()でそのような:

public function scopeWithVotesTrait($query, $model, $table) 
{ 
    return $query->join('votes', function($join) use($model, $table) 
    { 
     $join->on('votes.voteable_id', '=', $table . '.id') 
      ->where('votes.voteable_type', '=', $model); 
    })->select('*', \DB::raw('sum(vote) as votes')) 
    ->orderBy('votes')->groupBy($table . '.id'); 
} 

しかし、スコープを使うたびに$ model( 'App \ ParentModel')と$ table( 'parent_models')を手作業で入れなければならないと、そのようなことは特性に置く目的を打ち負かします。

スコープの最初の例で、投票の合計で効率的に注文する方法がありますか?または、モデル名を返すEloquent Modelから呼び出すことができる静的メソッドがあり、2番目の例を動作させるためにモデルテーブル用のメソッドがありますか?

他のアイデアでは、すべての投票の合計を親モデルに付けて注文するスコープを作成する方法はありますか?

答えて

4

私はjoinを使って2番目の例を扱うことにしました。 Eloquent \ Modelには、モデルのテーブル名を返す静的メソッドgetTable()がありますので、$ modelパラメータとして動的に渡すことができます。そして、私はPHP関数get_class()は、$ modelパラメータの親モデルのclassnameを持つ名前空間を返します。私は達成するために何を望むかについて

正しいクエリ:

public function scopeWithVotesTrait($query) 
{ 
    return $query->leftJoin('votes', function($join) use($model, $table) 
    { 
     $join->on('votes.voteable_id', '=', $table . '.id') 
      ->where('votes.voteable_type', '=', $model); 
    })->addSelect('*', $table . '.id', \DB::raw('COALESCE(SUM(vote),0) as votes')) 
    ->groupBy($table . '.id')->orderBy('votes'); 
} 

私もCOALESCEを追加した、まったく票が見つからない場合は、クエリの戻り0を行います。これはorderByが常に正しいためです。

また、ステートメントを選択するために*とparent_table.idも指定しました。 *を指定しないと、select文の中で指定したものだけが返されます。 parent_table.idを指定しないと、クエリではリレーションシップメソッド(例:Model :: withVotesTrait() - > with( 'some_other_child')で結果にsome_other_childが追加されません)をクエリできます。

また、私はjoinの代わりにleftJoinを使用しています。これにより、常に投票数に関係なくすべての親を返すようになりました。