2016-02-16 77 views
6

我有一個一對多的多態關係,就像in documentation所描述的一樣,除了我在投票表中有投票而不是照片和整數投票列。這樣的:Laravel 5.2關於多態關係的查詢範圍

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

投票模型具有voteable方法:

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

但我想有連接(第56頁在這個例子中)票我已經創建了一個VoteableTrait,裏面有模特票()morphMany方法和我試圖去工作的範圍。範圍將添加屬於某個模型的所有選票的總和,並按總和排序父模型。作爲範圍我已經試過:

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

但有了這個我不能排序依據爲Laravel執行2次不同的查詢,一個是父模型和一個似乎票。頁)結果:: 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調用的靜態方法返回模型名稱,另一個用於模型表格以使第二個示例工作?

任何其他想法如何使範圍,將所有投票的總和附加到父模型和它的順序?

回答

4

我已經得到它與使用連接的第二個示例一起工作。 Eloquent \ Model有一個靜態方法getTable(),它返回模型表名,所以我可以動態地將它作爲$ model參數傳遞。而我的PHP函數get_class()將爲$ model參數返回名稱空間和父類模型的類名。

什麼我想實現正確的查詢:

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添加到結果中)。

我也使用了leftJoin而不是加入,這樣它就會始終返回所有的父母,不管它連接的票數是多少。