tags:

views:

84

answers:

2

i am having trouble deciphering this block of code from doctrine documentation

/** @Entity */
class User
{
    // ...

    /**
     * @ManyToMany(targetEntity="User", mappedBy="myFriends")
     */
    private $friendsWithMe;

    /**
     * @ManyToMany(targetEntity="User", inversedBy="friendsWithMe")
     * @JoinTable(name="friends",
     *      joinColumns={@JoinColumn(name="user_id", referencedColumnName="id")},
     *      inverseJoinColumns={@JoinColumn(name="friend_user_id", referencedColumnName="id")}
     *      )
     */
    private $myFriends;

    // ...
}

below is how i decipher a one to many bidirectional relationship

alt text

but if i use the same method, ... below is what i get

alt text

UPDATE

i shld clarify my question. basically, i dont understand how is the opposite of myFriends, friendsWithMe. how i shld make sense of this code and more importantly know how to code such relationships myself.

A: 

i give a try at answering my question, i am still quite blur with this, hope someone can really give a better answer,

so 1st to answer the question abt how do i derive with $friendsWithMe

basically, i started off with "decoding" a simpler, more common, many to many bidirectional relationship.

  • 1 user can be in many groups
    • $user->groups
  • 1 group can have many users
    • $group->users

very straight forward. but how does this make sense in SQL?

alt text

code to implement

# select groups user is in
select group_id from users_groups
where user_id = 1

#select users of group
select user_id from users_groups
where group_id = 1

now to the actual model ... in SQL

alt text

in code

# select friends of given user
# $user->myFriends
select friend_id from friends
where user_id = 1;

# select users that are friends of given user
# $user->friendsWithMe
select user_id from friends
where friend_id = 1;

ah ha! select users that are friends of given user. so this is how i get $friendsWithMe. then to fill up the inversedBy & mappedBy & the rest of the class?

1st look at the bottom note.

alt text

not clear without so much and deep thinking, abt 2 days. i guess

then as practice how do i create a many to many self referencing relationship from scratch?

the example i am going to work on is... hmm, quite crappy i think but, i'll try :) ... 1 user/student can have many teachers. 1 teacher can have many users/students. 1 user can be a teacher and student here. u know like in forums such as these, when u answer someones questions, you are a teacher. when u ask, u are a student

the ERD will look like

alt text

some code to select, students of teachers, teachers of students

# select students of teacher
# $teacher->students
select student from teacher_student 
where teacher = 1;

# select teachers of student
# $student->teachers
select teacher from teacher_student
where student = 2;

ok, the doctrine part?

/** @Entity @Table(name="users")) */
class User {
    /**
     * @Id @Column(type="integer")
     * @GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @Column(type="string", length="30")
     */
    private $name;
    /**
     * @ManyToMany(targetEntity="User", inversedBy="teachers")
     * @JoinTable(name="Teachers_Students",
     *              joinColumns={@JoinColumn(name="teacher", referencedColumnName="id")},
     *              inverseJoinColumns={@JoinColumn(name="student", referencedColumnName="id")}
     *              )
     */
    private $students;
    /**
     * @ManyToMany(targetEntity="User", mappedBy="students")
     */
    private $teachers;
}

which generated this tables for me

# users
CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(30) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

#teachers_students
CREATE TABLE `teachers_students` (
  `teacher` int(11) NOT NULL,
  `student` int(11) NOT NULL,
  PRIMARY KEY (`teacher`,`student`),
  KEY `student` (`student`),
  CONSTRAINT `teachers_students_ibfk_2` FOREIGN KEY (`student`) REFERENCES `users` (`id`),
  CONSTRAINT `teachers_students_ibfk_1` FOREIGN KEY (`teacher`) REFERENCES `users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

at last i done it! lets test it ... erm i am getting

Fatal error: Class 'Entities\User' not found in D:\ResourceLibrary\Frameworks\Doctrine\tools\sandbox\index.php on line 61

when i try to do a

$user = new User;

zzz ...

i have also blogged abt this question and my explaination on my tumblr

jiewmeng
+1  A: 

The question is, having the M:N table:

  • friend_user_id
  • user_id

with two users id 1 and 2. Do you have only:

friend_user_id = 1 and user_id = 2

or both

friend_user_id = 1 and user_id = 2 user_id = 2 and friend_user_id = 1

You can implement both ways, depending on how you code the management of the collection of the owning side.

Case A:

public function addFriend(User $friend)
{
    $this->myFriends[] = $friend;
}

Case B:

public function addFriend(User $friend)
{
    $this->myFriends[] = $friend;
    $friend->myFriends[] = $this; // php allows to access private members of objects of the same type
}
beberlei
also regarding your new User issue, you have to understand how PHP 5.3 namespacing works, first you have to setup an autoloader for the "Entities" namespace, then you have to also call "use Entities\User;" to be able to do "new User" instead of "new \Entities\User;"
beberlei
regarding my User error, it turns out i didnt put a `namespace Entities` on top of my class declaration
jiewmeng
so i can say that Case 1 is a uni-directional relationship and 2 a bi? i think tho that if i am a user of a social network, where every1 can be friends with every1, i wont want to be friend with some1 just becos he added me as a friend? i have tested the M:N relationship that even in the self referencing/bi-directional setup, when some1 adds me as a friend, i am not a friend with him. it seems like its more of a convenience thing that i can find out who are friendWithMe?
jiewmeng
yes, sort of. Both the association and the contained data in it can be uni- or bi-directinoal in the case of Many-To-Many Self-Referential. Its a bit hard to grasp I agree, but that is always the case with self-referential stuff :-)
beberlei