Question
请注意,这个问题的解决方案就在下面,使用 Eugen 的视图思想!
我正在为 PHP/MySQL 用户驱动的网站编写一个聊天模块,允许两个用户交朋友,并选择 eJabberd 作为聊天系统。
我已经使用 PHP 守护程序成功设置了外部身份验证,现在我已经成功地通过使用将友谊添加到 eJabberd 中mod_roster_odbc
并填充 MySQLrosterusers
手动表。经过大量挖掘,我设法找到了这个特别的评论 http://www.ejabberd.im/node/2973#comment-52164对于了解将每一列设置为什么非常有帮助,以便在聊天模块的朋友列表中表示友谊。
我当前处理友谊的方法是将两行插入到rosterusers
table:
# Relationship user1 => user2
INSERT INTO rosterusers (username, jid, subscription, ask, server, type)
VALUES ('user1', '[email protected] /cdn-cgi/l/email-protection', 'B', 'N', 'B', 'item');
# Relationship user2 => user1
INSERT INTO rosterusers (username, jid, subscription, ask, server, type)
VALUES ('user2', '[email protected] /cdn-cgi/l/email-protection', 'B', 'N', 'B', 'item');
我对此不太满意,因为互惠的友谊需要两行。
据我了解,按照标准,XMPP 允许用户之间的单链接和双链接。根据我的问题的性质,人们可能会推断出,我自己的应用程序的朋友系统使用一行来代表友谊。
我的主要问题:
- 是否有可能将这种友谊巩固为一排?我尝试了一些组合非官方文档 http://www.ejabberd.im/node/2973#comment-52164但还没有成功。我正在通过使用 Pidgin 客户端连接到我的 XMPP 服务器进行测试。
- 保持两个数据库(朋友和 XMPP 花名册)同步的最佳方法是什么?我认为MySQL
TRIGGER
可能是目前最干净的选择。
如果没有,那么我的另一个选择是改变rosterusers
表并让它引用我自己的应用程序的朋友行,以便它的功能类似于跨数据库外键。
解决方案代码
我按照尤金的建议创建了一个视图。该代码不是最优雅的,但我已经对其进行了测试,它可以与 MySQL 5.5 上的 eJabberd 2.1 一起使用。
我的确切设置使用两个数据库,因此我通过使用显式引用我的主应用程序的数据库main_database.table_name
.
该代码是两个查询的联合 - 第一个查询获取 User, Friend,然后第二个查询插入 Friend, User。我在用着UNION ALL
为了速度,并让“重复”通过。
我认为这是处理问题的一种非常好的方法,因为不需要对应用程序进行任何更改,并且它会立即更新。
CREATE VIEW rosterusers AS
SELECT LCASE(ua1.Username) AS `username`, CONCAT(LCASE(ua2.Username), '@myserver.org') AS `jid`,
'B' AS `subscription`,
'N' AS `ask`,
'N' AS `server`,
'item' AS `type`,
'B' AS `subscribe`,
d1.Created AS `created_at`,
ua2.Username AS `nick`,
'' AS `askmessage`
FROM main_database.User_Friend AS `d1`
INNER JOIN main_database.User AS `ua1` ON `d1`.UserID = `ua1`.ID
INNER JOIN main_database.User AS `ua2` ON `d1`.FriendID = `ua2`.ID
WHERE d1.IsApproved = 1
UNION ALL
SELECT LCASE(ub2.Username) AS `username`, CONCAT(LCASE(ub1.Username), '@myserver.org') AS `jid`,
'B' AS `subscription`,
'N' AS `ask`,
'N' AS `server`,
'item' AS `type`,
'B' AS `subscribe`,
d2.Created AS `created_at`,
ub1.Username AS `nick`,
'' AS `askmessage`
FROM main_database.User_Friend AS `d2`
INNER JOIN main_database.User AS `ub1` ON `d2`.UserID = `ub1`.ID
INNER JOIN main_database.User AS `ub2` ON `d2`.FriendID = `ub2`.ID
WHERE d2.IsApproved = 1;