Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

BlastedAsh's avatar

Need help figuring out if this model should be polymorphic

Hey guys,

So I've hit a bit of a roadblock. So I have three tables of interest:

Table(simplified): Tickets

  • id (pk)
  • user_id (fk)
  • address_id (fk) (nullable)

Table(simplified): Users

  • id(pk)
  • address_id (fk)

Table(simplified): Address

  • id(pk)
  • type (0 for residence, 1 for ticket)
  • address

So Users upon sign up have to list their residence which gets stored in the meta_address table. When a user submits a ticket, they have the option to:

  1. Associate their Ticket with their residence address.
  2. Associate their Ticket with a different address / location

They also don't have to list an address associated with the Ticket, meaning the address_id field in Table::Tickets could be empty if need be.

So to recap with this logic there are 3 states:

STATE = NULL in the scenario where the ticket is regarding something that is not tied to a physical location. STATE = User Residence in the scenario where the ticket is regarding the users home address. STATE = Misc Location in the scenario where the ticket is any other type of address or coordinate.

Say meta_address table has a single row: id: 13 type: residence address: Foobar Road

During Ticket creation, when the User states that the Ticket is the same as their residence. I want the address_id in the Table:Tickets to be listed as '13'. I don't want it to create a new row.

If during Ticket creation, the user states a new address. I'd want a new row to be added to meta_address like this:

id: 14 type: ticket address: SegFault Ave

Now I'm not sure which route would be the best to do this. Would the morphTo() route be the best option here? Like this:

class Address { 
    public function addressable(){
        return $this->morphTo();
    }
}
class User { 
    public function address(){
        return $this->morphTo('App\Address','addressable');
    }
}
class Ticket { 
    public function address(){
        return $this->morphTo('App\Ticket','addressable');
    }
}

Anyone have any thoughts on this? Would this be the right way of doing this?

0 likes
5 replies
Vilfago's avatar

I don't think you need polymorphic, as the adress for residence could be the same as for ticket.

However, didn't you have to set a many relations, as a user will have many adresses? If not, how will you suggest which adress taken (from a previous ticket) ?

As I don't see any need to find adress which belongs only to user or ticket (in the contrary of comments for posts or videos), I will not advice you to choose polymorphic relations.

BlastedAsh's avatar

@Vilfago Thanks for your response. So each user can only have one address (their residence). Users cannot have more than one address associated.

The reason I thought I need to use a polymorphic relationship is because Two models (Users and Tickets) will be using the Address Model.

I may have explained it badly, but the gist is:

Users uses the Address model to store their residence address. Tickets uses the Address model to store addresses relating to the Ticket --> Ticket Model adds a new row in the Address table if the address is not the Users residence. -->Ticket Model references a pre-existing row in Address model if the address is the Users residence. The references row would be the row that belongs to the Users residence. --> Ticket Model doesn't interact with Address Model at all if the specific Ticket doesn't require an associated address.

If i don't make it polymorphic, how can I make two models (Users, Query) work with Address?

Vilfago's avatar

I'm worried about something the way you explain it :

Ticket Model adds a new row in the Address table if the address is not the Users residence.

User 1 has his residence in NYC - so it fill Adress Model He creates one ticket with adress to Denver - so it fill Adress Model He creates another ticket with adress to Denver - so it fill Adress Model He creates another ticket with adress to Denver - so it fill Adress Model He creates another ticket with adress to Denver - so it fill Adress Model etc.

It's always Denver, and it always add a line in the Adress table.

For me you have an Adresses table, with all adresses, and you don't care if it's used for an user residence of for a ticket. The user fill his adress, you use firstOrCreate to know if it exist or not, and you used the id returned by this function to fill the "adress_id" of your table. Done.

In this case, you will not have any duplicate record in the adress table, even if a ticket have the same adress as user's residence.

I don't see any advantage of polymorphic in this case, but I'm not a huge fan of polymorphic relationship (even if I had to use it sometime).

BlastedAsh's avatar

@Vilfago I think I confused you. Every user has to enter their residence address. The residence address gets stored in the Address table. Tickets can have an address if the address is relevant to the nature of the ticket, this address COULD be the users residence address IF it's relevant. Tickets can be submitted with an address attached to it - either residence, misc. or no address at all - but it depends on the nature of the ticket. Think of a ticket like a support ticket.

Say a tree is on fire at the park near your house. You submit a support ticket about the fire. It asks you whether the ticket is referring to a physical location, you hit yes and enter the address of the park. New address entry is present in the address table, and it's referenced in the Ticket table.

Now say your house is on fire, you want to submit a support ticket about a fire. It asks you "Is the ticket addressing an issue with your residence?" and you hit yes. Now you don't get to enter any address because the system already has your address on file. No new entry in the address table is necessary, all that needs to be done is the address_id to be returned and referenced.

Address Table could have duplicates, because say a Ticket_1 is created and uses Address X, and now Ticket_2 is created and also uses Address X. If Ticket_1 gets deleted, it'll delete Address X from the Address table returning an empty reference to Ticket_2.

In this case, I thought the only way for two individual models to interact with a third model is via some polymorphic relationship?

Vilfago's avatar

If Ticket_1 gets deleted, it'll delete Address X from the Address table

This information was missing, so I understand your point. But I'm not sure is a good practice, but I let the professional answer your points.

For polymorphic relations just ask you : "when will you need to know, in looking in the adresses table if the adress is related to a residence or a ticket".

If it's never (what I think, ad it's a pure relation table, you will never show adresses on their own), just do it simple.

Please or to participate in this conversation.