0

我想要实现的是一个复杂的隐私例程,我有下表。

帖子

帖子隐私

隐私全球

追随者名单

我们的网站上有一个新闻提要之类的东西,它从用户关注的人那里获取 10 个最新帖子,有 3 个隐私级别,第一个是 privacy_global,用户可以在他的帖子上设置隐私选项,0, 1 和 2 分别代表“只有我”、“所有人”、“仅限关注者”,然后有 posts_privacy 用户可以选择在发布之前列出他想要显示的人或隐藏帖子,此设置会覆盖privacy_global settings 和 posts_privacy 如果设置。

现在我的问题是,当我使用 php 在新闻提要中应用隐私时,我基本上要求这样的帖子。

SELECT `post`.*,
  `users`.`fullname`,
  `users`.`username`,
  `posts_privacy`.`hide`,
  `posts_privacy`.`show`,
FROM `post`
  LEFT JOIN `posts_privacy` ON `post`.`id`=`posts_privacy`.`postid`
  INNER JOIN `users` ON `post`.`userid` = `users`.`id`
WHERE (`post`.`userid` IN (1,2,3,4,5,6) 
AND 12 NOT IN (
  SELECT `hide` FROM `posts_privacy` WHERE `postid`=`post`.`id`)
  OR `show`= 12
)

 GROUP BY `post`.`id`
 ORDER BY `time` DESC LIMIT 10"

我无法弄清楚如何应用所有其他条件,在此之前我正在使用另一个查询并返回需要隐藏或显示帖子的人的序列化数组,然后在 php 中对其进行反序列化和处理,并从数组中删除该帖子在被发送到浏览器之前,这在新闻提要中造成了一个漏洞,而不是加载 10 个帖子,只出现了 6 个帖子,因为 php 在它们进入浏览器之前删除了 4 个具有隐私的帖子,我的目标是做所有的事情在帖子离开数据库之前 SQL 中的隐私条件,所以我对新闻源中帖子的计数没有这个问题。

我尝试查看 MySQL 函数和过程,但我被告知他们无法处理查询或返回表。

关于如何解决这个问题的任何建议?

编辑:如果有帮助,我正在尝试制作的系统与 Facebook 上的系统类似,用户可以在其中设置帖子特定的隐私,但也有全局设置,完成后会被覆盖。


表结构:

追随者名单:

id PRIMARY KEY BIGINT(20)
userid BIGINT(20) << 点击关注用户的id
targetid BIGINT(20) << 被关注用户的id

邮政:

id PRIMARY KEY BIGINT(20)
content TEXT
title VARCHAR(100)
time DATETIME
userid BIGINT(20)

帖子隐私:

id PRIMARY KEY BIGINT(20)
postid BIGINT(20)
隐藏 BIGINT(20)
显示 BIGINT(20)

4

1 回答 1

1

以下是获得所需结果的一种方法。不过,您需要进行一些仔细的测试,因为我已经没有时间进一步研究它了。它基于查看者的视角 - 请求他们有权查看的帖子的用户。它并不完美,所以请把它当作可以构建的东西。

最终版本中不需要查询返回的某些字段,但它们对于测试很方便:

SET @viewerid := 5;
SELECT
  p.id AS post_id,
  owner.id AS owner_id,
  pg.privacy AS privacy_global,
  pp.hide AS hide_from,
  pp.show AS show_to,
  f.userid AS viewer,
  f.targetid AS following
FROM posts AS p
JOIN users AS owner ON owner.id = p.userid
JOIN privacy_global AS pg ON pg.postid = p.id
LEFT JOIN posts_privacy AS pp ON pp.postid = p.id
LEFT JOIN followerlist AS f ON f.userid = @viewerid
WHERE ((pg.privacy = 0 AND pp.show = @viewerid)
OR (pg.privacy = 1)
OR (pg.privacy = 2 AND f.targetid = p.userid))
AND ((pp.hide != @viewerid OR pp.hide IS NULL)
AND (p.userid != @viewerid))
GROUP BY p.id
LIMIT 10;

在测试期间,您可能会发现分解查询很有用。以下块列出了帖子 ID、帖子所有者、全局隐私设置和隐藏/显示到用户 ID:

SELECT
  p.id AS post_id,
  owner.id AS owner_id,
  pg.privacy AS privacy_global,
  pp.hide AS hide_from,
  pp.show AS show_to
FROM posts AS p
JOIN users AS owner ON owner.id = p.userid
JOIN privacy_global AS pg ON pg.postid = p.id
LEFT JOIN posts_privacy AS pp ON pp.postid = p.id

添加查看者用户 ID,对于查看者关注该帖子所有者的每个帖子,将显示额外的行:

SET @viewerid := 1;
SELECT
  p.id AS post_id,
  owner.id AS owner_id,
  pg.privacy AS privacy_global,
  pp.hide AS hide_from,
  pp.show AS show_to,
  f.userid AS viewer,
  f.targetid AS following
FROM posts AS p
JOIN users AS owner ON owner.id = p.userid
JOIN privacy_global AS pg ON pg.postid = p.id
LEFT JOIN posts_privacy AS pp ON pp.postid = p.id
LEFT JOIN followerlist AS f ON f.userid = @viewerid;

然后,这些WHERE条款继续根据每个帖子和全局隐私设置缩小这些结果的范围。

于 2010-07-26T09:16:12.903 回答