guice's avatar
Level 4

Laravel and Polymorphism

I need to run this by a larger hive mind to get my bearings here. I need to build a polymorphic translating object.

The intent is normalizing third party api data. The root is they are all "resource planning" systems. We use several; so, I'm looking to build a normalizer. I could have sworn Eloquent supported "_type" columns for polymorphic objects, not model relationships. However, all my Googling isn't showing any ability to do, essentially, the opposite what Laravel's docs are showing.

This is what I'm after:

organization_table
  // normalized data and columns here -- translated to/from via the normalizer classes
  - erp_unique_id // the third party ERP ID
  - erp // the Laravel Model class, e.g. `App\Models\Erp\Erp1`; `App\Models\Erp\Erp2`

And upon return, $orgModel->erp would be automatically translated to to associated erp class.

It's the opposite of the relationships Laravel is promoting. As such, I'm getting really lost trying to conceptually grasp how Eloquent is doing "Polymorphic Relationships." Honestly, so much so, I'm literally googling Polymorphism to make sure I'm not seeing this incorrect. šŸ˜… A polymorphic object is a "German" or "French" object extending "Person." How is Eloquent viewing this?

I'm hoping this is a "This is 'exactly' what Polymorphic Relationships are for," and I'm just missing it ...

0 likes
4 replies
guice's avatar
Level 4

i.e.:

For example, a blog Post and a User may share a polymorphic relation to an Image model.

@ivanwitzke This is where I'm confused. In this sentence, I hear a Post and a User object store their data within a single Image data, and you're using the relationship in Image to relate back either a Post and User. It sounds like a simple one-to-one relationship vs polymorphism, i.e. an "image type" of UserImage and PostImage containing data unique to both of those, "extending" the base Image object. Do you follow what I was seeing? To be more specific, I was looking for "imageable" to pull things like "type_jpeg" with jpeg meta, vs "type_svg" with svg meta, or "type_gif" with gif specifics (speed, length, etc).

That's my biggest confusion. The examples look like a standard one-to-one relationship.

@snapey Your post, however, using the idea of User Profiles is exactly what I was thinking about: the "imageable" relationships are an extension of, not "belong to", the profile, i.e. your main User object as all the user data, and the different profile types include different data based on which profile_type is associated.

When changing up the demo model with my scenario, I can see how they are "the same thing" in practice, but (in my view) different in concept:

erp_a
    id - integer
    name - string
    unique_to_A - string
 
erp_b
    id - integer
    name - string
    unique_to_B - string
 
organzation
    id - integer
    name - string
    owner - string
    erp_type_id - integer
    erp_type - string // Models\ErpA or Models\ErpB
   // storing in `erp` property

In this instance, the erp is now a polymorphic object with the extended fields for that specific erp type instance -- A or B.

Snapey's avatar

I wrote that post.

Laravel's polymorphic relationship simply allows a relation to be defined as a model and key rather than just the key. So the model column tells eloquent the type of the related record, and the ID points to the instance.

It may help if all the choices of related models have similar schema, but thats definitely not mandatory (its not trying to do a union).

Please or to participate in this conversation.