Dev*_*evK 7 php laravel eloquent laravel-5.2
我有一对多的多态关系,完全像文档中描述的那样,除了我在投票表中有投票而不是照片和整数投票列.像那样:
-votes
--id
--vote
--voteable_id
--voteable_type
Run Code Online (Sandbox Code Playgroud)
投票模型具有可投票的方法:
public function voteable()
{
return $this->morphTo();
}
Run Code Online (Sandbox Code Playgroud)
但是对于我希望附加投票的模型(本例中的页面),我创建了一个VoteableTrait,它具有votes()morphMany方法和我试图开始工作的范围.范围将添加属于某个模型的所有投票的总和,并按总和对父模型进行排序.我试过的范围:
public function scopeWithVotesTrait($query)
{
return $query->with(['votes' => function($q){
$q->select(\DB::raw("SUM(vote) AS votes"), 'voteable_id')->first();
}]);
}
Run Code Online (Sandbox Code Playgroud)
但是,由于Laravel执行2个不同的查询,一个用于父模型,一个用于投票,因此我无法订购.Page :: withVotesTrait() - > first()的结果将投票放在一个数组中:
{
"id": 1,
"votes": [
{
"votes": "-1",
"voteable_id": 1
}
]
}
Run Code Online (Sandbox Code Playgroud)
我的另一个想法是执行连接而不是 - > with(),如下所示:
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');
}
Run Code Online (Sandbox Code Playgroud)
但是如果我每次使用示波器时都必须手动输入$ model('App\ParentModel')和$ table('parent_models'),那么这就是将其置于特征中的目的.
那么在我的第一个范围示例中,有没有一种方法可以通过投票总和进行有效排序?或者是否有任何静态方法可以从Eloquent Model调用返回模型名称,还有一个用于模型表以使第二个示例有效?
任何其他想法如何制作一个范围,将所有投票的总和附加到父模型和它的订单?
我已经让它与使用 join 的第二个示例一起使用。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');
}
Run Code Online (Sandbox Code Playgroud)
我还添加了 COALESCE,如果没有找到投票,这将使查询返回 0。这样 orderBy 总是正确的。
我还指定了 * 和parent_table.id 来选择语句。如果没有 *,查询将只返回我们在 select 语句中指定的内容。如果没有parent_table.id,查询将不会返回我们可能使用关系方法查询的任何模型(例如:Model::withVotesTrait()->with('some_other_child') 不会将 some_other_child 添加到结果中)。
我还使用 leftJoin 而不是 join,以便它始终返回所有父级,无论与其相关的投票数如何。
归档时间: |
|
查看次数: |
1747 次 |
最近记录: |