How do I setup super- and sub-type relationships in CodeIgnitor's DataMapper ORM?

321 views Asked by At

I'm running an online food journal where users can record journal entries. There are four types of entries: food entries, exercise entries, measurements, and completed tasks. Entries have several attributes in common (e.g., id, amount, unit_id, etc), but they also have type-specific attributes (e.g., food_id, exercise_id, etc). That's a perfect candidate for a super- and sub-type relationship.

Here are my tables (simplified):

CREATE TABLE entries
`id` int
`user_id` int
`created` datetime
`entered` datetime
`amount` float
`unit_id` int
PRIMARY KEY id

CREATE TABLE exercise_entries
`entry_id` int
`exercise_id` int
PRIMARY KEY entry_id

CREATE TABLE food_entries
`entry_id` int
`food_id` int
PRIMARY KEY entry_id

So my question is, how do I setup super- and sub-type relationships using CodeIgniter's DataMapper ORM? I've looked at the User Guide's Relationships and Advanced Relationships sections, but I can't find anything.

If it's not possible with DataMapper, I can think of a few solutions:

  1. Roll sub-type attributes up (1 big table, ugh)
  2. Roll super-type attributes down (4 separate tables, ugh)
  3. Go nuclear and use Doctrine 2.0 ORM (YAML config files, ugh!)
  4. Use a different framework whose native ORM supports table inheritance (I shortlisted Kohana and FuelPHP with CodeIgniter).
  5. Manually code super- and sub-type relationships (defeats purpose of ORM in the first place).

I'm not thrilled with any of my options. Option 1 and 2 create their own headaches (see the bottom of this article). Option 3 seems like surgery with a sledgehammer. I'm open to Option 4 because I haven't started writing any framework code (it was a really tough choice between CI and Kohana). Option 5 is where I am now.

Any suggestions? Thanks for the help!

1

There are 1 answers

2
swatkins On BEST ANSWER

I haven't tried this with DataMapper, but you might try (making sure to call the parent constructor and all that). I would assume that Exerciseentry would inherit all of the properties/methods from Entry - but not sure if DataMapper would handle it this way:

class Entry extends DataMapper {

}

// you may have to explicitly include Entry.php in this file:
class Exerciseentry extends Entry {

}

If that doesn't work, you can basically create two objects that are related ( not really pure OOP principle, but would get the job done ):

class Entry extends DataMapper {
    // ... some stuff

    var $has_many = array('exerciseentry', 'foodentry'); 

    // ... some more stuff
}

class Exerciseentry extends DataMapper {
    // ... some stuff

    var $has_one = array('entry');

    // ... some more stuff
}

class Foodentry extends DataMapper {
    // ... some stuff

    var $has_one = array('entry');

    // ... some more stuff
}

// then when you get an entry, you'd do this
$my_exercise_entry = new Exerciseentry(1);
$my_exercise_entry->include_related('entry', array('user_id', 'amount', 'unit_id');
$my_exercise_entry->get();

echo 'Amount is: ' . $my_exercise_entry->entry_amount;
// etc