Welcome Guest, Not a member yet? Register   Sign In
One-way relationships with DataMapper?
#1

[eluser]mscott809[/eluser]
I'm pretty much a noob here, and just getting started with DataMapper, but one thing I haven't been able to find is if DataMapper can support one-way (i.e., with no inverse) relationships. For example, let's say I want to track the user who last modified any given record (and therefore have a "last_mod_by_id" column in all my tables), but I don't care to be able to (easily) find out what records where last modified by a given user. I don't want to create a large join table or add unnecessary inverse foreign key columns for this when a one-way relationship will do the job.

I realize I can just manage this myself by storing the id of the user in this field and doing the lookup by id manually, but that's nowhere near as easy as letting DataMapper handle this for me.

Thanks.
#2

[eluser]mscott809[/eluser]
I guess the question might be, can I just define the relationship on one model and not the other, or will DataMapper have issues with that? (I see from the FAQ and other questions posted here that this is something people accidentally do fairly frequently. But if I intentionally do this, will I get the one-way relationship behavior I'm looking for, or will I just get a pants-load of trouble?)

Code:
class User extends DataMapper {
  var $has_one = array();
  var $has_many = array();
}

class Record extends DataMapper {
  var $has_one = array(
    'last_mod_by' => array(
      'class' => 'User',
      'other_field' => ''
    )
  );
  var $has_many = array();
}
#3

[eluser]WanWizard[/eluser]
Yes, Datamapper will have issues with that, because depending on how you construct your queries, relationship information from either side is used.

Since this is a plain has_one relation, that should not be an issue, as it will refer to $user->id (which is an existing column, so no extra keys) and has_one doesn't need a relationship table.
#4

[eluser]mscott809[/eluser]
In this case (tracking who last modified a record), the relationship from the record to the user who last modified it is to-one, but the inverse is to-many (one user can have many records they were the last one to modify) and it's this inverse relationship I don't care about and so don't want to have the overhead of maintaining.

It sounds like I have to manage this on my own (by manually getting/setting the last_mod_by_id field and performing my own get on the User). In my case, I can put this particular logic into my intermediate sub-class (per my other thread) so my main models won't have to know the difference.

Is there a way for me to file a feature request to have DM support one-way relationships? They can be quite useful.

Thanks for the quick response!

-Scott
#5

[eluser]WanWizard[/eluser]
May I suggest you read the manual before you make assumptions as to how things work?
Code:
class Parent extends Datamapper
{
    public $has_many = array('child');
}

class Child extends Datamapper
{
    public $has_one = array('parent');
}

// get a child
$child = new Child(1);

// get it's parent
$child->parent->get();

Tell me, where is the maintenance in this? Of course, if you choose non-standard naming, you'll have to add a few lines more, but that is entirely your choice. Can't make it easier than this.

And to your last question: relations are never one-way. Or do you have a relation with your girlfriend, but she doesn't have one with you?
#6

[eluser]mscott809[/eluser]
[quote author="WanWizard" date="1309639479"]May I suggest you read the manual before you make assumptions as to how things work?[/quote]

I have read the manual "cover to cover." I would never waste somebody's time before RTFM. The manual does a good job of documenting two-way relationships, but makes no mention of one-way, hence my question.

[quote author="WanWizard" date="1309639479"]Tell me, where is the maintenance in this?[/quote]

It's not the code maintenance I'm concerned about--you're correct, there isn't anything to maintain as far as code goes. I'm concerned about the maintenance of the join table that the database and DM will have to do. I have no need for the to-many side of the relationship so I'd rather not have the overhead of maintaining this join table. Maybe this is a premature optimization, but I expect to have 10s of thousands to 100s of thousands of records in this DB, and nearly every one of them is going to be represented in this join table that I won't need.

Quote:And to your last question: relations are never one-way. Or do you have a relation with your girlfriend, but she doesn't have one with you?

While that's conceptually true, there are places where one-way relationships are useful, and they're certainly not unheard of in the ORM world. (Apple's CoreData offers one-way relationships, for instance.) DataMapper appears to be 98% of everything I need, and I can manage this one-way stuff myself, so I'll do that.

Sorry if I stepped on any toes. :red:
#7

[eluser]WanWizard[/eluser]
As I was trying to explain to you in my first reply, there is no join (or relationship) table. This is explained in between the two covers, so you must have read it... Wink

There is only a join table when you have a many-to-many relation. In all other cases, Datamapper uses an ITFK (in-table foreign key), exactly as you have it designed now.
#8

[eluser]mscott809[/eluser]
[quote author="WanWizard" date="1309654248"]As I was trying to explain to you in my first reply, there is no join (or relationship) table. This is explained in between the two covers, so you must have read it... Wink

There is only a join table when you have a many-to-many relation. In all other cases, Datamapper uses an ITFK (in-table foreign key), exactly as you have it designed now.[/quote]

Oh, OK, that makes sense now. I was a bit confused, I think by this statement in the "Advanced Relationships" section:

Quote:We only have the option in this case because the posts side was $has_one. If posts could have many creators or many editors, then that would have to be stored in this table.

But in looking over that page and the Relationship Types page with this in mind, I see that what you say is what is being described. It just wasn't very clear to me.

Thanks for clarifying!
#9

[eluser]WanWizard[/eluser]
That text is related to the intro above the table, which starts with "If we decide to use a join table, that table is a little different..."

Datamapper allows you to use a join table, even on a has_one relation. If it exists, it will be used. If not, an ITFK will be used.

You will usually opt for a join table if your relationship has properties, which you would have to store in the join table (for example, the timestamp of when the relation was made). Although technically with a has_one you could store these fields in the 'one' table together with the ITFK, it's not a very clean solution.




Theme © iAndrew 2016 - Forum software by © MyBB