Нужна помощь в понимании доктрины много-много кода, ссылающегося на себя - PullRequest
7 голосов
/ 20 июля 2010

У меня проблемы с расшифровкой этого блока кода из документации доктрины

/** @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;

    // ...
}

ниже показано, как я расшифровал двунаправленное отношение один ко многим

альтернативный текст http://29.media.tumblr.com/tumblr_l5uwg3VH171qbp1vqo1_r1_500.png

но если я использую тот же метод, то ... вот что я получаю

альтернативный текст http://img514.imageshack.us/img514/2918/snagprogram0000.png

UPDATE

Я должен уточнить мой вопрос. в принципе, я не понимаю, как это противоположно myFriends, friendsWithMe. как я должен понимать смысл этого кода и, что более важно, знать, как самому кодировать такие отношения.

Ответы [ 2 ]

10 голосов
/ 21 июля 2010

я пытаюсь ответить на мой вопрос, я все еще довольно размышляю над этим, надеюсь, кто-то действительно сможет дать лучший ответ,

, поэтому сначала ответьте на вопрос о том, как мне получить с$friendsWithMe

По сути, я начал с «декодирования» более простых, более распространенных, двунаправленных отношений между многими.

  • 1 пользователь может быть во многих группах
    • $ user-> groups
  • 1 группа может иметь много пользователей
    • $ group-> users

очень прямо.но как это имеет смысл в SQL?

alt text

код для реализации

# 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

сейчас для фактической модели ... в SQL

alt text

в коде

# 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;

ах ха! выберите пользователей, которые являются друзьями данного пользователя .так вот как я получаю $friendsWithMe.затем, чтобы заполнить inversedBy & mappedBy & остальную часть класса?

1-й взгляд на нижнюю ноту.

alt text

непонятно, без долгих размышлений, около 2 дней.я предполагаю

тогда как на практике, как мне создать отношения «многие ко многим» со ссылками на себя с нуля?

пример, над которым я собираюсь работать, это ... хммЯ думаю, довольно глупо, но я попробую :) ... 1 пользователь / студент может иметь много учителей.1 учитель может иметь много пользователей / учеников.1 пользователь может быть учителем и учеником здесь.Вы знаете, как на форумах, подобных этим, когда вы отвечаете на чьи-то вопросы, вы учитель.когда вы спрашиваете, вы студент

, ERD будет выглядеть следующим образом:

alt text

какой-то код для выбора, ученики учителей, учителя учеников

# 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;

хорошо, часть учения?

/** @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;
}

, который сгенерировал эти таблицы для меня

# 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

наконец я это сделал!давайте проверим это ... я получаю

Неустранимая ошибка: класс 'Entities \ User' не найден в D: \ ResourceLibrary \ Frameworks \ Doctrine \ tools \ sandbox \ index.php в строке 61

когда я пытаюсь сделать

$user = new User;

zzz ...

, я также написал в блоге об этом вопросе и моих объяснениях на моем tumblr

3 голосов
/ 23 июля 2010

Вопрос в том, чтобы иметь таблицу M: N:

  • friend_user_id
  • user_id

с двумя пользователями с идентификатором 1 и 2. Выиметь только:

friend_user_id = 1 и user_id = 2

или оба

friend_user_id = 1 и user_id = 2 user_id = 2 и friend_user_id = 1

Вы можете реализовать оба способа, в зависимости от того, как вы кодируете управление коллекцией владеющей стороны.

Дело A:

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

Дело B:

public function addFriend(User $friend)
{
    $this->myFriends[] = $friend;
    $friend->myFriends[] = $this; // php allows to access private members of objects of the same type
}
...