【问题标题】:PHP - Add users as friendsPHP - 将用户添加为好友
【发布时间】:2010-12-16 20:29:35
【问题描述】:

我有一个社交网站,你可以加好友。它的工作方式是这样的:

  • 点击加好友
  • 添加点击的用户 数据库行,在列中像这样 [鲍勃][弗雷德][123123]
  • fred 在验证中接受它并附上秘密 链接,通过电子邮件发送。
  • 然后将另一行放入 反过来数据库,比如 这个 [fred][bob][123123]

然后我可以确定他们是否是朋友以及他们是否已被接受。

但是,这肯定不是正确的方法。我现在非常不确定哪种方法可以更好,运行更顺畅。

【问题讨论】:

  • 请注意,提出这么宽泛的问题相当于问“我怎样才能用英语写一篇关于美国内战的文章?谈论奴隶制是个好主意吗?”

标签: mysql database-design


【解决方案1】:

真的没有正确或错误的方法,它是你决定使用什么,归根结底它是你的代码,所以无论你选择什么并为你工作。

但是,您说得很对,输入两行将是一个非常沉重的开销,并且似乎没有充分的理由使用额外的空间。更简单的是,您可以在数据库中设置另一列:

user_1 | user_2 | accept_code | accepted

user_1 请求将 user_2 添加为好友 - 您设置了 accept_code 在数据库中创建条目。将您的数据库结构设置为将accepted 列设置为define as false。然后当第一次创建行时,用户当前不是朋友。

使用你的例子:鲍勃请求弗雷德作为朋友。你的数据库现在看起来像这样:

bob | fred | 123123 | false

user_2进入accept_code时,将accepted改为true。

bob | fred | 123123 | true

这样,一个查询将告诉您这两个用户是否是朋友,而不是两个查询来查看您是否有两个匹配的数据库条目。

例如,bob 已将 fred、joe 和 alex 添加为好友,fred 和 alex 已接受 bob 作为好友,但 joe 没有。你的数据库看起来像这样:

user_1 | user_2 | accept_code | accepted

bob | fred | 123123 | true

bob | joe | 321321 | false

bob | alex | 789789 | true

因此,例如,一个伪选择可能会找到 bob 的所有朋友:

SELECT user_2 FROM relationships WHERE user_1="bob" AND accepted="true"

结果是:

fred alex

根据 cmets 更新:

数据库结构:

user_1 | user_2 | accept_code | accepted

bob | fred | 123 | true

bob | alex | 123 | true

bob | joe | 123 | false

ste | bob | 123 | true

joe | alex | 123 | true

选择语句:

SELECT * FROM relationships WHERE accepted = 'true' AND (user_1 = 'current_user' OR user_2 = 'current_user');

示例 1 - bob 登录,他已请求好友并被请求为好友:

SELECT * FROM relationships WHERE accepted = 'true' AND (user_1 = 'bob' OR user_2 = 'bob');

结果:

bob | fred | 123 | accepted

bob | alex | 123 | accepted

ste | bob | 123 | accepted

示例 2 - alex 登录,他从未请求过好友但已被请求为好友:

SELECT * FROM relationships WHERE accepted = 'true' AND (user_1 = 'alex' OR user_2 = 'alex');

结果:

bob | alex | 123 | accepted

joe | alex | 123 | accepted

示例 3 - joe 登录,他请求了一个朋友并拒绝了一个朋友:

SELECT * FROM relationships WHERE accepted = 'true' AND (user_1 = 'joe' OR user_2 = 'joe');

结果:

joe | alex | 123 | accepted

【讨论】:

  • 那么我如何检查 fred 是否是 bob 的朋友?因为使用你所说的sql查询,它不会返回任何东西,因为fred没有发送请求。
  • 简单地说:`SELECT user_1, user_2 WHERE accepted="true" AND (user_1="bob" OR user_2="bob");然后,您将拥有完整的朋友列表。有关示例,请参阅帖子的更新。
【解决方案2】:

社交网络数据库关系很快就会变得非常复杂,尤其是在流量扩大和请求涌入时。Facebook 等主要来源的开发者博客中提供了大量数据,说明他们如何修改和调整系统以适应随着流量的增加而扩展。

没有任何一种正确的方法可以创建关系 - 这取决于您的代码结构 - 但是说执行您的两个查询以创建简单的一对一关系并复制数据被正确地假设为不必要的额外高架。

您可以创建一个简单的联结表,其中包含两个用户的 ID,一个字段保存发起请求的人(用户的 int 主键),另一个字段接收批准请求(也是 int 主键。 ) 你可以有另一个状态 int 字段,其数值对应于关系的状态。

您应该始终使用数字键作为您的用户身份 - 您永远不知道有多少 'John's 会加入!确保您甚至只有一个简单的“用户”表,其中包含唯一键的用户 ID。

UserID|Name
1      Frank
2      John

这当然可以包含其他信息、姓氏、位置、性别、最喜欢的西尔维斯特史泰龙电影等。

可以在具有以下结构的单独关系表中创建关系...因此,当 Frank (id 1) 请求 John (id 2) 时,我们最终会得到这样的一行。

RelationshipID|RequestedBy|Receipient|RequestStatus|ConfirmationCode
(primary key)       1           2        0            (however you format your url strings)

然后,您就可以拥有所有关系的主键。每个单独的链接都是可识别的。

另外,我个人会集成另一个表来定义状态变量。

StatusIdentifier|StatusDefinition
0                 Requested but not yet approved
-1                Requested and denied (mark for deletion)
1                 Requested and approved (active friendship)

通过这种方式,如果您想要更多,可以在程序中扩展关系类型,例如加好友然后删除、阻止等。在我部署的大多数应用程序中,这种数据非常适合 XML ,但是将其放入数据库中并没有错。接收者的响应必须获取RelationshipID,然后更新此状态值。

为关系表的更新添加时间戳也是一个好主意。

使用这种结构,您可以使用用户表中的主 ID 轻松查询所有用户的朋友。让我们将 Franks 放入一个数组中:

$sql = 'SELECT Recipient FROM FriendRelationships WHERE RequestedBy = 1 AND RequestStatus = 1';

这会获取 Frank 的所有活跃朋友用户 ID,因为他是请求者 (1),我们限制为已获得收件人批准的请求。

【讨论】:

  • 对基础知识的精彩讨论。在讨论时间戳时也可以讨论乐观和悲观锁定。我还建议将诸如“最喜欢的史泰龙电影”之类的无关信息放入基于用户的弱实体的配置文件表中,因为这更有可能改变。用户只需要一个主键、姓名和电子邮件地址(我假设你应该总是有一些联系方式)
  • @Visionary Software Solutions - 完全同意,Sly 只是为了缓解喜剧效果,否则整个事情都会变得很枯燥。我遵循相同的做法——我几乎总是将这种无关的配置文件信息放在单独的 ProfileDetails 表中,或者序列化并保存为与用户对象模型一起加载的与用户相关的平面文件格式。我认为 OP 正试图在一些非常基本的东西上进行调整,所以我只是把它作为一个粗略的大纲。感谢您的评论!
  • 谢谢你,但我很困惑如果他们没有向某人发送请求,我就无法获得其他人的朋友。例如:如果 34 加 67 那么我如何查看 64 的朋友?包括 34,因为只有 34 发送请求时 sql 才会接收它。
  • @hart1994 基本上任何两个同时出现的状态为 1 的用户都是链接的。请求最初传输的方向并不重要,我只是提供了该特定查询,因为它符合您提供的问题的上下文。您可以处理两个方向的所有行,然后 array_unqiue 键,然后构造您的用户对象。或者您可以创建一个仅表示数据链接的 MYSQL 视图。具体口味由您决定。
【解决方案3】:

你可以试试这个逻辑。

假设 bob 想要将 fred 添加为朋友。

  1. bob 发送 fred 添加为好友

    操作:将数据库查找表作为好友:[bob] [fred] [仅隐藏,当 bob 接受时使其可见]

  2. fred 在验证后接受请求 行动:使[隐藏] ---> [可见]

    现在您与用户和朋友建立了关系。[查找表中的每一行都是朋友]

    希望这会有所帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 2019-01-09
    • 1970-01-01
    • 2013-07-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多