I’ve a problem figuring out how to configure the mapping of my classes with Doctrine2.
Let say I’ve these tables:
Address table
---------------------
- id
- civic_no
- road
- state
- country
PersonnalAddress table
---------------------
- id
- base_address_id
- type
- is_primary
BusinessAddress table
---------------------
- id
- base_address_id
- business_name
- shipping_phone
- is_primary
And thoses PHP objects:
class Address{}
class BusinessAddress extends Address{}
class PersonalAddress extends Address{}
Considering the following requirements:
- An address can exist by itself (the Address class is not abstract)
- A personalAddress and a businessAddress can have the very same address data
- If I delete or edit the address, it has an impact on all the business or personal address that are inherited from it.
- I don’t want any data duplication in the database (this is a requirement of the 2nd normal form)
- Proxy methods mean code duplication, I prefer not to have any.
- Magic methods are not good in term of testability, I prefer not to have any.
To better illustrate the problem, I expect the data in the data base to look like:
Address table:
id | civic_no | road | state | country
1 123 test qc ca
PersonnalAddress table:
id | base_address_id | type | is_primary
1 1 A 0
2 1 B 1
BusinessAddress table:
id | base_address_id | business_name | shipping_phone | is_primary
1 1 chic choc 1231234 1
What would be the best strategy to implement a solution that match theses requirements ?
Ok this is a bit of a long one but I think it covers all your bases, if you have any questions then feel free to ask.
This comes with a caveat that I don’t know if you can do
Many-To-Oneon a MappedSuperclass. If that isn’t possible then you may be able to use Class Table Inheritance instead. Give it a try and tell us if it works.Keep in mind I pushed this code out pretty quickly, it is untested so it may not be correct but hopefully you’ll get the idea of how it works.
Here we go!
Interface to make it easier to say “what is an address” without making abstract classes then overriding methods and causing the “bad design” feeling 😉
Abstract Entity which you don’t really need but if you dont use it you need to duplicate the ID code.
BasicAddress which you can store alone or have linked to a “ComplexAddress”
“ComplexAddress” is just here to let you re-use the code for delegating calls to a basic address.
PublicAddress
BusinessAddress
Edit: Just noticed I forgot to put cascade parameters for deletion, you might need to handle this directly though – when a
BasicAddressis deleted also delete the other addresses that use it.