Drummerkolle's avatar

Eloquent Has many over different models with index sort

Hi everybody,

I'm kind of stuck what to do for my use case, or better which relation to choose for it...

I want to have a table for multiple webpages (landingpages). Each page should have modules which are different types and tables (one should be text, one should be an image, one should be an entire different model, aso). I also need to order the modules and I tried to wrap my head around it but failed...

I think it should be something like an "inverse polymorphic many to many"?!?

Because I don't need one model, that can be used for multiple other models (like tags for posts or comments), but more like multiple models, that can be used on one model (the page)

Maybe it's just the normal polymorphic many to many and I just have thought to much about it and confused myself, but at this point I don't know anymore...

If I would go with that I would have the following tables:

landingpages module_images module_links module_text...

but what would be the relation table then?

landingpageable?

That just sounds so wrong...

I could then add an order column (index) to the landingpageable and call that from the landingpages model?!? Right now that I write this, it sounds kind of ok to me, but as said, I just don't know anymore...

Can someone confirm, that this would be the way to do it? Or give me a hint, what to do...

Thanks!

0 likes
3 replies
martinbean's avatar

@drummerkolle Yeah, you’ve got a polymorphic relation there. Just try and keep things simple by going over your use case and picking out the nouns.

When you describe your entities and their relationships, you can translate that to code. For example: you have a landing page that has many modules, which can by of any type.

So if you have a LandingPage model that has a has-many relationship with a Module model, that model can have a polymorphic relationship to the actual content type (text, image, etc). The modules table would have the polymorphic relation columns (i.e. module_type and module_id), but can also have other columns, such as one for storing the sorting index for your modules for a particular landing page.

Hope that helps!

Drummerkolle's avatar

Hi @martinbean, sorry I was away for the weekend and had no chance to try it... First of all thanks for your input, I've given it another shot today and am still not sure, how to do it correctly.

The problem I struggle with is, that all examples on the Laravel docs are the inverse from what I need...

So for example the many-to-many polymorphic relation:

A tag BELONGS TO a post or a video. The problem starts, when I try to project it on my models...

The TAG is querying as follows:

public function posts()
{
   return $this->morphedByMany('App\Post', 'taggable');
}

public function videos()
{
   return $this->morphedByMany('App\Video', 'taggable');
}

And then in the POST it would be:

public function tags()
{
    return $this->morphToMany('App\Tag', 'taggable');
}

But as said, this is the wrong way around...

For me it would be: A landingpage HAS MANY modules of different kinds. So as far as I understand it, I always need to query all relations (for each moduletype I implement). My guess is, that I need to merge the queries and can not do it with the build in eloquent relations?

I haven't found a way to get all relations automatically yet, I always have a problem with retrieving all relationships without calling then explicit (also with an interim modules model, because I need to call the individual moduletypes there too)...

Sorry, maybe I'm thinking way to complicated or still don't understand the eloquent relationships fully, but as said, from what I've read in the docs, my use-case is simply missing or at least not documented in a way that I understand it...

Maybe I'm to focused on the examples of the site and need to look more into the functionalities itself...

Any further nudge in the right direction is highly appreciated!

martinbean's avatar

@drummerkolle I gave you the solution. A landing page has many modules like you say. A module would then have a polymorphic relationship pointing to the relevant model for that “module type”—text, image, etc.

So when you query a landing page, fetch its module relation and whatever you call the polymorphic relation:

$landingPages = LandingPage::with('module.modulable')->get();

The polymorphic “modulable” relation would be your Text model or Image model or whatever.

Please or to participate in this conversation.