1

I have an application that requires:

user owns many projects. project has one owner.

user works on many projects. projects have many users.

so I have 3 tables, users, projects_users, projects. The relationships are:

one user (owner) --- many projects (created_by)

many users (id) ---- via projects_users (user_id, project_id) ---- many projects (id).

In Codeigniter I've set up the following relationships in the datamapper models:

Class Project extends DataMapper {

var $has_one = array(
    'created_by' => array(
        'class' => 'user',
        'other_field' => 'owns'
    )
);
var $has_many = array('user' => array(
        'class' => 'user',
        'other_field' => 'project',
        'join_table' => 'projects_users'));

and...

    class User extends DataMapper {

var $has_many = array(
    'project' => array(
        'class' => 'project',
        'other_field' => 'user',
        'join_table' => 'projects_users'
    ),
    'owns' => array(
        'class' => 'project',
        'other_field' => 'created_by'
    )
);

This doesn't seem to work however and I get a recursive error. What is the correct way to represent this relationship in datamapper?

Stevo
  • 2,601
  • 3
  • 24
  • 32
  • right - I see, my 'other' fields are not reciprocal. A result of staring at code too long. – Stevo Jan 20 '12 at 08:04

1 Answers1

1

Take a look at Multiple Relationships to the Same Model on the doc page: http://datamapper.wanwizard.eu/pages/advancedrelations.html

I'm guessing something like this:

class Project extends DataMapper {
    $has_one = array(
        'owner' => array(
            'class' => 'user',
            'other_field' => 'owned_project'
        )
    );
    $has_many = array(
        'user' => array(
            'class' => 'user',
            'other_field' => 'user_project'
        )
    );
}

class User extends DataMapper {
    $has_many = array(
        'owned_project' => array(
            'class' => 'project',
            'other_field' => 'owner'
        ),
        'user_project' => array(
            'class' => 'project',
            'other_field' => 'user'
        )
    );
}

and you would access like this:

$project = new Project(1); // where "1" is the ID of the project
$owner = $project->owner->get();
$project_users = $project->user->get();

// -------------------------------

$me = new User(1); // where "1" is the ID of the user
$my_projects = $me->owned_project->get();

UPDATE

You will need to update your projects_users join table to this:

projects_users
--------------
user_id
owner_id
owned_project_id
user_project_id

Note that these all match the "keys" that you declared in your $has_one and $has_many arrays. You will not need to update the users or projects tables (the only requirement is that each of them have a primary key field named "id").

swatkins
  • 13,530
  • 4
  • 46
  • 78
  • What you're suggesting is a one-to-one and a many-to-many. I want a one-to-many and a many-to-many. – Stevo Jan 19 '12 at 20:58
  • I've edited this (not sure if it was before your comment). Here's the explanation: `Project has one owner.` `Project has many users.` `User has many owned projects.` `User has many projects.` -- So there's a 1 to many on owner -> project. There's a many to many on user -> project. – swatkins Jan 19 '12 at 21:03
  • Hi, I must have commented first. At first glance, mine and yours don't seem too dissimilar. I'll have a good look. Thanks for the pointer. – Stevo Jan 20 '12 at 07:55
  • So, this is where my confusion lies: I want to use the id field in the users table as the 'owner' identity. In your solution is the 'owned_project' field just a key defined in datamapper or does it map to a field in the database - the implication being I need another join table? – Stevo Jan 20 '12 at 08:20
  • The 'owned_project' is just a key. You only need the one join table. However, you need to add additional fields to it. I forgot that part. When I get to the office, I'll add that part to the answer. – swatkins Jan 20 '12 at 14:24
  • I've just updated the answer to indicate changes to the join table. Let me know if you have any problems with this. – swatkins Jan 20 '12 at 14:57
  • Thanks - I hadn't tried that. It makes sense. I'll have a go when I get back onto it. – Stevo Jan 20 '12 at 17:27