-1

While querying polymorphic relationship existence or absence, Laravel Eloquent provides whereHasMorph and whereDoesntHaveMorph methods which really helpful to create queries related to the types. But what about for eager loads?

Here is the situation:

Think about 3 models App\Photos, App\Videos and App\Blogs.

These three models are all feedable which means they have a polymorphic relationship with App\Feed model.

But while App\Photos and App\Videos models are reactable (have a polymorphic relationship with App\Reactions model), App\Blogs model doesn't have this relationship.

Let's check out the methods:

App\Feed

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

App\Reactions

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

App\Photos

public function feed() {
    return $this->morphOne('App\Feed', 'feedable');
}

public function reactions() {
    return $this->morphMany('App\Reactions', 'reactable');
}

App\Videos

public function feed() {
    return $this->morphOne('App\Feed', 'feedable');
}

public function reactions() {
    return $this->morphMany('App\Reactions', 'reactable');
}

App\Blogs

public function feed() {
    return $this->morphOne('App\Feed', 'feedable');
}

While querying feeds from App\Feed model, I also want to get reactions count. But because of that App\Blogs model doesn't have a method named reactions, this query causes errors.

How can I create query like this:

$feeds = Feed::with([
    'feedable' => function($query) {
        // I need to get the feedable_type of the feedable here.
        // module_exists is a custom helper to check if an module is installed and active
        if ($type != 'App\Blogs' && module_exists('Reactions')) {
            $query->withCount('reactions');
        }
    }
])->all();

Edit

I have tried to simplify my question but I think I need to provide more information about the application.

The application is a content management system (social network system) that third party developers can develop modules for. Blogs, Photos, Videos, Feed, Reactions, Comments, Share etc. are all different modules and they can be disabled or removed by the site owners. So while developers are creating modules, they have to take into consideration that Reactions, Coments etc modules can be disabled or removed.

Hüseyin Dursun
  • 550
  • 5
  • 15

1 Answers1

1

1- Naming conventions in Laravel states that models are singular form, so you may consider renaming the models to Photo and Video etc..

2- In your case, the Blog model doesn't have reactions, so you may create a type Scope in the Feed model like:

public function scopeHasReactions($query)
{
    return $query->whereIn('reactable_type', ['App\Photo', 'App\Video']);
}

3- use $withCount property to get counts, in Photo model in example:

protected $withCount = ['reactions'];

Finally you can make a query like this:

$feeds = Feed::hasReactions()->get();

$feeds->first()->reactions_count;

Hope this helps.

Yamen Ashraf
  • 2,637
  • 2
  • 20
  • 26
  • Thanks for your answer. I have just updated my question according to your answer. Please check it again. 1. Different modules can have Photo, Video etc models. 2. All of the feeds whether they are reactable or not will be displayed. So I want to get not only reactable ones but also the unreactables. 3. If site owner disables or removes Reactions module, this will cause error. – Hüseyin Dursun Sep 24 '19 at 09:05
  • You can think about adding a reactions_count property to the Blog model with the value of zero and hide it in the view. – Yamen Ashraf Sep 24 '19 at 11:06