Support the ongoing development of Laravel.io →
posted 9 years ago
Eloquent
Last updated 2 years ago.
0

Use this:

class Post extends Eloquent {

    // if you don't want it to be appended always, don't set this one - see below
    protected $appends = ['rating'];

    protected $hidden = ['ratingsSum'];

    public function ratingsSum() {
        return $this->hasOne('Rating')
            ->selectRaw('sum(rating) as aggregate, post_id')
            ->groupBy('post_id');
    }

    public function getRatingAttribute()
    {
		if ( ! array_key_exists('ratingsSum', $this->relations)) $this->load('ratingsSum');

		$relation = $this->getRelation('ratingsSum');

		return ($relation) ? $relation->aggregate : 0;
    }
}

Then you can do this:

$posts = Post::with('ratingsSum')->get();
$posts->toArray();
array(
  ...
  'rating' => '8'
)

// but mind that without eager loading you will face n+1 queries issue:
$posts = Post::get();
$posts->toArray(); // db call for ratingsSum() for each post

If the above (using $appends) doesn't suit you, don't set it and instead do this:

$posts = Post::with('ratingsSum')->get();
foreach ($posts as $post) { $post->setAppends(['rating']); } // when you need it

or leave $appends but don't load rating on demand in the accessor

    public function getRatingAttribute()
    {
		$relation = array_get($this->relations, 'ratingsSum');

		return ($relation) ? $relation->aggregate : null;
    }

// then
$posts = Post::get();
// 'rating' => null

$posts = Post::with('ratingsSum')->get();
// 'rating' => '8'
Last updated 9 years ago.
0

Sign in to participate in this thread!

Eventy

Your banner here too?

croshim croshim Joined 13 Jan 2015

Moderators

We'd like to thank these amazing companies for supporting us

Your logo here?

Laravel.io

The Laravel portal for problem solving, knowledge sharing and community building.

© 2024 Laravel.io - All rights reserved.