1

When designing a relationship in Datamapper one is bound to call the relationship the same name as the related object, which is not too handy when you have something like Application_Model_User as a class name. For those of you who will rush to say that there is a configuration option with "class" key, I know. Been there tried that. It only works for getting a related object, not for updating them.

Here is a code snippet to reproduce the problem:

// User Model
class UserModel extends Datamapper
{
    public $table = 'users';
    public $has_many = array(
        'roles' => array(
            'class' => 'RoleModel',
            'other_field' => 'usermodel',
            'join_other_as' => 'role',
            'join_self_as' => 'user',
            'join_table' => 'users_roles' 
        ),
    );
}

class RoleModel extends DataMapper
{
    public $table = 'roles';
    public $has_many = array(
        'usermodel' => array('class'        => 'UserModel',
                         'other_field'  => 'roles',
                         'join_other_as'=> 'user',
                         'join_self_as' => 'role',
                         'join_table'   => 'users_roles' )
    );
}

// controller code. Make sure you have a role with INT id = 2, and a user with INT id = 5 in your db
$user = new UserModel(2);
$role = new RoleModel(5);
$user->save($role);

This code gives an "Unable to relate usermodel with rolemodel." error, however it does work properly (meaning a new record is inserted in the join table user_roles) if the relation is renamed from "roles" to "rolemodel".

So, if there are any avid users of CI's Datamapper that could help, please let me know how to properly define relationships.

Wesley Murch
  • 101,186
  • 37
  • 194
  • 228
Slavic
  • 1,891
  • 2
  • 16
  • 27

1 Answers1

2

UPDATE

You can save an object as a relation using the relationship key:

$object->save( $related, $relationship_key ). 

So you would need to use

$user->save($role, "roles");

See the bottom of this web page: http://datamapper.wanwizard.eu/pages/save.html


Leaving this bit in case it helps someone else out.

It looks like you want to have a custom name on a relationship. (That's what I get after wading through all of the cynicism) -

You get to name the relationship anything that you want with the key in the relationship array. So, in the following snippet, you use book <-- this does or does not have to be the same name as the class - that's what the class key is for.

class Author extends DataMapper {
  $has_many = array(
    'book' => array(  // YOU USE THIS KEY TO NAME THE RELATIONSHIP
        'class' => 'book',
        'other_field' => 'author',
        'join_self_as' => 'author',
        'join_other_as' => 'book',
        'join_table' => 'authors_books'
     )
  );
}

If this is not working for you, my guess is you have something else wrong in the set up of your relationships.

http://datamapper.wanwizard.eu/pages/advancedrelations.html

Daan
  • 7,685
  • 5
  • 43
  • 52
swatkins
  • 13,530
  • 4
  • 46
  • 78
  • Hello swatkins, seems you haven't waded long enough :). I wrote: "For those of you who will rush to say that there is a configuration option with "class" key, I know. Been there tried that. It only works for getting related object, not for updating them". I will briefly supply an exmaple as well to prove my point. – Slavic Jan 03 '12 at 15:06
  • 1
    OK, I misunderstood your question (code helps). You can save an object as a relation using the relationship key: `$object->save( $related, $relationship_key )`. So you would need to use `$user->save($role, "roles");` See the bottom of this page: http://datamapper.wanwizard.eu/pages/save.html – swatkins Jan 03 '12 at 15:27
  • Please write this as an answer (just edit your answer). This does seem like the solution. Problem is documentation denotes the second parameter as optional, thus leaving me to believe that it is only required when relationships haven't been fully defined, which is not my case. Well, it turns out it's not like that. – Slavic Jan 03 '12 at 15:30
  • In response to your comment above, if the second parameter is omitted, then DM only knows the $role as "RoleModel" - it will only know "roles" as it pertains to the relationship with "UserModel". Because you've explicitly named the relationship key, you have to use that in the `save()` method. – swatkins Jan 03 '12 at 15:47
  • I thought of that, but in that case, it would not make sense to have a "'other_field' => 'roles'," in the RoleModel itself.. – Slavic Jan 03 '12 at 15:53
  • 1
    I see where you're going with that, but the problem comes in if you want multiple "separate" relations to the same model. Say you want to use the `RoleModel` class as both "roles" and "departments". Then you'd have two separate keys to use to relate RoleModel to UserModel. That's why you have to explicitly add the relation key in the save method. Otherwise, DM would have to "guess" at the relation. – swatkins Jan 03 '12 at 16:07