Laravel 5.2 query area for polymorphic relationships

I have one, many polymorphic relationships, as described in the documentation , except that I have voices instead of photos and columns with an integer number of votes per vote. For instance:

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

The Voting Model has a voting method:

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

But for the models to which I want to add votes (Page in this example), I created a VoteableTrait that has a vote () method morphMany and the area that I am trying to get. The volume will add the sum of all the votes belonging to a particular model and order the parent models with the sum. Scope I tried:

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

But with this, I cannot orderBy, since Laravel makes 2 different requests, one for the parent model and one for the voices that seems. The result of the page :: VotesTrait () → first () puts the voices in an array:

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

Another idea I had was to make a connection instead of → with () as follows:

 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'); } 

But if I have to manually put $ model ('App \ ParentModel') and $ table ('parent_models') every time I use the scope, it hits the target to put it in the line.

So, is there a way to efficiently sort by the sum of the votes in my first example sphere? Or is there any static method that you could call from the Eloquent Model that will return the model name and one for the model table to make a second example?

Any other ideas on how to create an area that will attach the sum of all the votes to the parent model and organize it?

+6
source share
1 answer

I have this for working with a second example using join. Eloquent \ Model has a static getTable () method that returns the name of the model table, so I can dynamically pass it as $ model parameter. And the php get_class () function will return a namespace with the class name of the parent model for the $ model parameter.

The correct request is what I wanted to achieve:

 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'); } 

I also added COALESCE, which will make the request return 0 if no votes are found. This is so that orderBy is always valid.

I also specified * and parent_table.id to select the operators. Without *, the query returns only what we specify in the select statement. And without parent_table.id, the request will not return any models that we could request using the relationship methods (example: Model :: withVotesTrait () → with ('some_other_child') will not add some_other_child to the result).

I also used leftJoin instead of joining so that it always returns to all parents, regardless of the number of votes associated with it.

+4
source

All Articles