views:

48

answers:

2

Hello,

I'm trying to do an association of two objects with Doctrine (PHP).

I have two objects : User and Conversation

One user has many conversations and a conversation belongs to two users maximum (on initiator of the conversation, and one receiver).

So, in my Doctrine class I have this in the Conversation class :

$this->hasOne('User as Initiator', array('local' => 'initiator_id', 'foreign' => 'id'));
$this->hasOne('User as Responder', array('local' => 'responder_id', 'foreign' => 'id'));

And in the User class :

$this->hasMany('Conversation as Conversations', array('local'=> 'id', 'foreign'=> ????));

For this foreign key I'd like to put something that means "initiator_id OR responder_id".

I guess I need a junction table to accomplish what I want to do ? What would you do in this case ?

Thank you for your answers,

Martin

+1  A: 

my guess would be this:

$this->hasMany('Conversation as Initiations', array('local'=> 'id', 'foreign'=> 'initiator_id'));
$this->hasMany('Conversation as Responses', array('local'=> 'id', 'foreign'=> 'responder_id'));
ITroubs
No, this wouldn't work because I want to access to all the conversation of one user just by doing something like $user->Conversations; and with your solution it might not be possible.
MartinMoizard
I see your problem. hmm it's a pretty interesting question. the manual of doctrine doesn't cover this special case which isn't even that unusual. so +1 for your question
ITroubs
A: 

I think it would be better to re model the relation between the Conversation and User tables to manytomany. because even though a conversation have only 2 users, they are still considered more than one.

In the previous solution, Having Two has-many relations with the same table (Conversation) is an over head. because you will end up doing twice the work every time you query a a conversation.

My suggestion is to change the relation between the conversion and the user to hasMany and reference them using an association class ConversationParticipants that contains the conversion_id, user_id and an additional association attribute called type to indicate the type of the user (Initiator/Responder).

So you will end up with something similar to this ( the code is not tested !)

class Conversation extends Doctrine_Record {

    public function setTableDefinition() {

        // Your Table Fields
    }

    public function setUp() {

        // Your Setup Code

        $this->hasMany('User as Users', array(
                'local' => 'conversation_id',
                'foreign' => 'user_id',
                'refClass' => 'ConversationParticipants'
            )
        );
    }

}

class User extends BaseUser
{

    public function setTableDefinition() {

        // Your User Fields

    }

    public function setUp()
    {

        // Your Setup Code

        $this->hasMany('Conversation as Conversations', array(
                'local' => 'user_id',
                'foreign' => 'conversation_id',
                'refClass' => 'ConversationParticipants'
            )
        );
    }
}

class ConversationParticipants extends Doctrine_Record
{
    public function setTableDefinition()
    {
        $this->hasColumn('user_id', 'integer', null, array(
                'primary' => true
            )
        );

        $this->hasColumn('conversation_id', 'integer', null, array(
                'primary' => true
            )
        );

        $this->hasColumn('type', 'string', 255);

    }
}

This is how i would've implemented it on any ORM, I'm not sure though if you can use association attributes in Doctrine or if this way of molding is going to work as I'm not an expert in Doctrine

I Hope this was helpful ,,,

Manaf Abu.Rous
Thank you very much for your answer, I already modeled it like you advised me it looks pretty good. I didn't try with the association attribute though (the type of conversation) cause I think that Doctrine doesn't allow it, so I kept my two hasOne User in the Conversation class.
MartinMoizard