The model of the (PHP & MySQL based) application I'm currently working on contains a inheritance similar to the one described here. Simplified for the purpose of this question the classes structure can look like this:
To map this to the database I'm using the Class Table Inheritance design pattern. Here is the physical data model:
The most specific attributes are actually specific for every single subclass. But there are some attributes, that are needed in several classes (but also not in all of them -- otherwise they could be managed in the Foo
class/table). When it's a simple attribute, it causes some code duplication, but isn't a big problem. But there are also some cases with complex attributes.
E.g.: FooTypeBaz
and FooTypeBuz
should contain a list of Whatever
elements.
Normally I would implement this 1:n
relationship with a table whatever
containing FOREIGN KEY
. But in this case I would need multiple FOREIGN KEY
columns whatever
(for foo_type_baz
, foo_type_buz
, and maybe some tables more). It's dirty.
Another solution: Something like a "facade" table for the table whatever
:
Looks better (for me), but I'm still not happy with this model.
How to build a relationship between multiple sub-entities and a collection/list attribute? Is there an elegant solution for this problem? Maybe a best practice / design pattern?
Recording the relationship is easy enough - you could make a table
foo_whatever (foo_id PK, whatever_set_id FK)
and insert rows only for appropriate foo ids. However, that schema doesn't enforce any constraint on the subtypes you can associate with whatever sets, but neither does your existing schema enforce that subtypes are mutually exclusive. It's possible to enforce both with the same technique.Consider including a type indicator on all the
foo_*
tables, e.g. using anenum('bar', 'baz', 'buz')
. This provides subtype information infoo
(which can be more convenient than joining 3 tables to find a match) and allows foreign key constraints and check constraints to enforce exclusive subtypes and restrict the types that can be recorded infoo_whatever
. Yes, it involves a bit of redundant information, but it's small and there's no risk of update anomalies.Using composite foreign key constraints that involve a type indicator, together with check constraints that limit the value of the type indicator for each subtype table, should do the trick. Here's the schema I suggest:
However, since MySQL ignores check constraints, you would need to use triggers to achieve the same: