I've almost finished my Data Mapper, but now I'm at the point where it comes to relationships.
I will try to illustrate my ideas here. I wasn't able to find good articles / informations on this topic, so maybe I'm re-inventing the wheel (for sure I am, I could just use a big framework - but I want to learn by doing it).
1:1 Relationships
First, lets look at 1:1 relationships. In general, when we've got an domain class called "Company" and one called "Address", our Company class will have something like address_id. Lets say in most cases we just display a list of Companies, and the address is only needed when someone looks at the details. In that case, my Data Mapper (CompanyDataMapper) simply loads lazily, meaning it will just fetch that address_id from the database, but will not do a join to get the address data as well.
In general, I have an getter method for every Relationship. So in this case, there's an getAddress(Company companyObject) method. It takes an company object, looks for it's address property and - if it's NULL - fetches the corresponding Address object from the database, using the Mapper class for that Address object (AddressDataMapper), and assigns that address object to the address property of the specified company object.
Important: Is a Data Mapper allowed to use another Data Mapper?
Lets say in most cases you need both the company object AND the address object, because you always display it in a list all together. In this case, the CompanyDataMapper not only fetches company objects, but does an SQL query with JOIN to also get all the fields of the address object. Finally, it iterates over the record set and feeds new objects with their corresponding values, assigning the address object to the company object.
Sounds simple, so far.
1:n Relationships
How about these? The only difference to 1:1 is, that an Company may have multiple Address objects. Lets have a look: When we're most of the time only interested in the Company, the Data Mapper would just set the addresses property of the company object to NULL. The addresses property is an array which may reference none, one or multiple addresses. But we don't know yet, since we load lazily, so it's just NULL. But what, if we would need all the addresses in most cases as well? If we would display a big list with all companys together with all their addresses? In this case, things start to get really ugly. First, we can't join the address table fifty times for every address object (I strongly believe that's impossible, and if it is, performance would be below zero). So, when we think this further down the road, it's impossible to NOT load lazily in this case.
Important: Is this true? Must I send out 100 queries to get 100 address objects, if I have 10 companies with each 10 addresses?
m:n Relationships
Lets say an address object only contains the country, state, city, road and house number. But one house could be a big business tower with lots of companies in them. Like one of those modern office buildings where anyone can rent a small rom to show off that tower on its website. So: Many companies can share the same address.
I have no plans yet to deal with that kind of problem.
Important: Probably it's not a bigger problem than the 1:n Relationships?
If anyone knows a good ressource that goes into details about solving / implementing this, I would be happy about a link!