|
Cake-PHP.ru Форум программистов CakePHP (на сайт)
|
Предыдущая тема :: Следующая тема |
Автор |
Сообщение |
dedmusos
цитировать
Зарегистрирован: 08 Янв 2008 22:37:19 Сообщения: 8
|
Добавлено: 08 Янв 2008 22:42:27 Заголовок сообщения: Ассоциация сама с собой |
|
|
Господа, представьте - у нас есть таблица пользователей (users). Теперь перед нами встает задача, создать на сайте такой сервис, как друзья (как на ВКонтакте, грубо). То есть, теперь нам нужно пересвязать элементы таблицы users друг с другом. Получается, что нам нужна доп. таблица friends, но как таковой сущности friends не существует, посему вопрос - как реализовать следующее?
users
id | name |
friends
user_id | friend_id
и связать все это ассоциацией, чтобы иметь возможность во запросу findAll() получить, ко всему прочему, список друзей?
Здесь обязательно создание класса Friend, пусть и фиктивного? |
|
Вернуться к началу |
|
|
Борис
цитировать
Зарегистрирован: 08 Янв 2008 00:26:04 Сообщения: 8
|
Добавлено: 08 Янв 2008 23:10:40 Заголовок сообщения: |
|
|
Таблица friends, а лучше friendships, необходима, так как здесь будет связь 1 к n (или даже n к n, если забыть, что друг тоже будет пользователем).
Если бы у каждого человека мог быть только один друг, то есть связь 1 к 1, то достаточно было бы дополнительного поля friend_id в таблице users.
Можно создать "фиктивных" пользователей - друзей других пользователей, но тогда таблица users будет хранить не только пользователей, но и друзей (как отдельных сущностей) всех пользователей, что неверно с точки зрения подхода.
Если бы по человеку надо было находить лишь его друзей, то можно было бы "вывернуться", создав текстовое поле, в которое распаковывать массив друзей. Если я буду другом для своего друга, то есть связь будет двухсторонней, то метод может быть вполне удачным, но реализовать его придётся самому. |
|
Вернуться к началу |
|
|
dedmusos
цитировать
Зарегистрирован: 08 Янв 2008 22:37:19 Сообщения: 8
|
Добавлено: 08 Янв 2008 23:56:32 Заголовок сообщения: |
|
|
Борис
Благодарю, но все вышеописанное Вами мне известно. Считаю, что единственно верный способ с точки зрения БД - это создать таблицу friendships и пересвязать там пользователей как n к n.
Посему вопрос - как реализовать подобную ассоциацию в Cake?
Проблема вот в чем - если пересвязывать как HABTM, то нам обязательно надо будет указать на класс, с которым мы связываем ассоциацию. Можно ли указать собственный класс? |
|
Вернуться к началу |
|
|
Антон Исайкин Site Admin цитировать
Зарегистрирован: 08 Окт 2007 12:02:56 Сообщения: 150 Откуда: Санкт-Петербург
|
Добавлено: 09 Янв 2008 09:09:33 Заголовок сообщения: |
|
|
Очень знакомая ситуация, реализовывал такое, правда давно. Тогда ничего лучше не придумал, чем в модель user добавить свою функцию вроде такой:
Код: |
function getFriends($uid) {
// тут обращаемся к таблице friends таким запросом
SELECT user_id, friend_id FROM friends WHERE user_id = $uid OR friend_id = $uid
// дальше перебираем результат
$friendIds = array();
foreach ($result['Friends'] as $row) {
$friendIds[] = $row['user_id'] == $uid ? $row['friend_id'] : $row['user_id'];
}
return $friendIds;
}
|
Соответственно при добавлении друга проверяем, нет ли уже такой связи. |
|
Вернуться к началу |
|
|
dedmusos
цитировать
Зарегистрирован: 08 Янв 2008 22:37:19 Сообщения: 8
|
Добавлено: 09 Янв 2008 14:33:13 Заголовок сообщения: |
|
|
Антон Исайкин
Идеологически это, конечно, не то, что бы неверно, скажем так - лишено изящности...((( |
|
Вернуться к началу |
|
|
Sam Dark
цитировать
Зарегистрирован: 09 Ноя 2007 19:16:48 Сообщения: 19
|
Добавлено: 09 Янв 2008 19:34:15 Заголовок сообщения: |
|
|
Модель:
Код: | var $hasAndBelongsToMany = array(
'Friend' =>
array('className' => 'User',
'joinTable' => 'users_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'friend_id',
),
'Admirer' =>
array('className' => 'User',
'joinTable' => 'users_users',
'foreignKey' => 'friend_id',
'associationForeignKey' => 'user_id',
),
); |
Контроллер:
Код: | function addfriend($friend_id = null) {
$this->data = $this->User->read(array('id'), $this->obAuth-
>getUserId());
$friends = array();
foreach ($this->data['Friend'] as $friend) {
$friends[] = $friend['id'];
}
$friends[] = $friend_id;
$admirers = array();
foreach ($this->data['Admirer'] as $admirer) {
$admirers[] = $admirer['id'];
}
$admirers[] = $friend_id;
unset($this->data['Friend']);
unset($this->data['Admirer']);
$this->data['Friend']['Friend'] = $friends;
$this->data['Admirer']['Admirer'] = $admirers;
if ($this->User->save($this->data)) {
$this->Session->setFlash('Added to Friends.');
}
} |
Запускаем /users/addfriend/10. 10-ый добавлен к друзьям залогиненого, залогиненый добавлен к друзьям 10-го.
(c) red (english cakephp google group) |
|
Вернуться к началу |
|
|
dedmusos
цитировать
Зарегистрирован: 08 Янв 2008 22:37:19 Сообщения: 8
|
Добавлено: 09 Янв 2008 21:12:05 Заголовок сообщения: |
|
|
Sam Dark
Красавчик! Люблю профессионалов своего дела...
Самому, право, стыдно, хоть я и третий день кейк изучаю ((( |
|
Вернуться к началу |
|
|
Антон Исайкин Site Admin цитировать
Зарегистрирован: 08 Окт 2007 12:02:56 Сообщения: 150 Откуда: Санкт-Петербург
|
Добавлено: 09 Янв 2008 22:04:14 Заголовок сообщения: |
|
|
red конечно попал в стиль Cake, но сколь велик смысл дубля всех записей?
А если в результате ошибки из двух записей останется одна? Получится, что Иван федору друг, а вот Федор Ивану -- нет. |
|
Вернуться к началу |
|
|
|
|
Вы можете начинать темы Вы можете отвечать на сообщения Вы можете редактировать свои сообщения Вы можете удалять свои сообщения Вы не можете голосовать в опросах
|
Powered by phpBB © 2001, 2005 phpBB Group Русская поддержка phpBB
|