Ну, я опаздываю на вечеринку, но вот моя ставка.
Первые столы:
User
-id
Type
-id
Relationship
-user_id_1
-user_id_2
-type_id
Теперь я хочу, чтобы моя таблица типов была простой. Таким образом, типы, которые я добавляю, представляют только отношения одного пользователя с другим. Они никогда не представляют двунаправленные отношения. Например:
friend
ignored
Это облегчает добавление новых типов. Мне не нужно думать или создавать все возможные комбинации всех моих типов. Я просто добавляю новый тип.
Чтобы установить дружбу, вам нужно 2 записи в таблицу отношений. Если оба пользователя согласны с тем, что они друзья, они друзья. Если только один говорит, что он дружит с другим, а другой заблокировал его, они не друзья.
Делать запросы очень просто. Вот как вы получаете всех друзей в MySQL:
SELECT u.* FROM user u
LEFT JOIN relationship r1 ON u.id = r1.user_id_2
LEFT JOIN relationship r2 ON u.id = r2.user_id_1
WHERE r1.user_id_1 = <my_user_id> # my relationship with them
AND r1.type_id = <friend_type_id> # i say i'm a friend
AND r2.user_id_2 = <my_user_id> # their relationship with me
AND r2.type_id = <friend_type_id> # they say they're friends
Я также считаю, что такой подход более безопасен для транзакций. Представьте, что вы отправили кому-то запрос о дружбе, а затем заблокировали этого человека. Если этот человек позже примет запрос на добавление в друзья, это не имеет значения. Это не меняет состояния отношений, потому что они полностью независимы.
Если бы вместо этого у вас был один тип, который представлял двунаправленные отношения, вы были бы вынуждены сделать своего рода оценку в своем коде того, каким именно должно быть новое состояние отношений, как только друг принял запрос друга. Если вы этого не сделаете, вы можете в итоге разблокировать пользователя и подружить его с пользователем, которого он заблокировал.
Я бы предпочел справиться с этим на уровне базы данных. Если у вас есть несколько программистов, работающих над приложением, это не займет много времени, прежде чем кто-то забудет об этой проблеме где-нибудь, и будет создана труднодоступная ошибка.