【问题标题】:Database design to log user actions in WordPress在 WordPress 中记录用户操作的数据库设计
【发布时间】:2012-11-23 15:34:59
【问题描述】:

我需要一个表格来记录用户在 WordPress 中所做的某些操作。

到目前为止,这是我已经准备好的数据库架构:

id bigint(20) NOT NULL AUTO_INCREMENT,
uid bigint(20) NOT NULL,
type VARCHAR(256) NOT NULL,
data1 TEXT NOT NULL,
data2 TEXT NOT NULL,
data3 TEXT NOT NULL,
timestamp bigint(20) NOT NULL,
UNIQUE KEY id (id)

让我澄清一下:

uid: User ID of the wordpress user
type: Type of action the user made (can be 'comment', 'new_post', 'login', etc)
data1/2/3: additional data (for example, ID of comment or post made)

要显示日志,我会查询数据库并运行某个过滤器以获取要为该特定日志显示的文本。所以它的工作原理是这样的:

if( $type == 'comment') {
    $comment = get_comment( $data1 );
    $user = get_user($uid);
    echo "User {$user->name} has made a <a href='{$comment->permalink}'>comment</a>";
}

这是最有效的做事方式吗?这对我来说似乎很好,因为我不想只将 HTML 存储在要输出的日志表中。

但是,问题出现在我想在满足某些条件时隐藏特定日志条目的地方。例如,如果评论不再存在,我想隐藏该条目。这会给分页带来一些问题。关于如何克服这个问题的任何建议?

谢谢!

编辑:

myplugin_transactions
id bigint(20) NOT NULL AUTO_INCREMENT,
user_id bigint(20) NOT NULL,
type VARCHAR(256) NOT NULL,
timestamp bigint(20) NOT NULL,
UNIQUE KEY id (id)

myplugin_meta
id bigint(20) NOT NULL AUTO_INCREMENT,
txn_id bigint(20) NOT NULL,
key VARCHAR(256) NOT NULL,
data TEXT NOT NULL,
UNIQUE KEY id (id)

假设我想从 myplugin_transactions 中选择 *,其中 data1 通常是 'x' 而 data2 是 'y'。这种情况应该怎么做?

SELECT * FROM myplugin_transactions LEFT JOIN myplugin_meta ON myplugin_transactions.id = myplugin_meta.txn_id WHERE ( ... ? )

【问题讨论】:

  • 您的数据类型可能会更好。 user_id 真的需要BIGINT 吗?你预计会有超过 40 亿的用户吗? timestamp 列应该是 TIMESTAMP 类型。尽量避免TEXT类型;它将强制在磁盘上进行任何排序。除非您确实需要超过 255 个字符,否则请使用 VARCHAR(255)。主表上的type 列可能应该是VARCHAR(255),因为将其设为256 会增加一个额外的字节。这些更改可以显着减小数据和索引的大小。
  • @G-Nugget 感谢您就 VARCHAR(255) 与 VARCHAR(256) 之间的性能差异提供意见。如果我使用 TIMESTAMP 类型,会有任何性能改进吗?我也选择了 BIGINT 而不是 INT,因为它与 WordPress 数据库模式 (codex.wordpress.org/Database_Description/3.3#Table:_wp_users) 一致。他们可能使用 BIGINT 来实现可扩展性。我是一名插件开发人员,这是为公众编写的。然后我应该使用 INT 还是坚持使用 BIGINT?
  • 如果您保持一致,我想使用BIGINT 很好。时间戳值实际上是多少?它是 unix 时间戳还是格式化日期?另外,总是在将行插入表时还是在其他时间?你还应该让你INT 输入字段UNSIGNED;使用BIGINT,您可能不会注意到任何区别,但这是正确的做法。
  • @G-Nugget 这将是一个 unix 时间戳。我有时想获取一小时前的条目,并且会选择时间戳大于 。另外,我读了这个(stackoverflow.com/a/409305/1365792)。就我而言,日期时间不应该比时间戳更合适吗?我对使我的 INT SIGNED 或 UNSIGNED 的含义一无所知。
  • 创建INT 类型UNSIGNED 使其只能具有正值,从而有效地将最大值加倍。 TIMESTAMP 可能是最好的类型。如果你真的需要用时区来操作时间,你可以转换它。 TIMESTAMP 更小,基本上是服务器的 unix 时间戳。 TIMESTAMP 还具有能够使用当前时间作为默认值的好处,允许您通过省略时间戳并让服务器使用当前时间来简化查询。

标签: php mysql database wordpress database-design


【解决方案1】:

此答案将非常通用,因为它不提供任何代码,但评论也太长了。

首先,您不应该在data1data2data3 字段中存储额外的数据。您正在使用 MySQL,因此您拥有关系数据库的强大功能。使用它们。

您应该简单地拥有另一个表,其中包含一个 ID 字段(操作的 ID)和一个数据字段。这样,您可以将 0 存储到任意数量的元数据中。我的意思是,wordpress 已经用元数据做到了,对吧?

其次,如果评论被删除,你是否只是想删除与之相关的操作?如果是这样,只需连接到 API。我相信delete_comment有一个钩子:http://codex.wordpress.org/Plugin_API/Action_Reference#Comment.2C_Ping.2C_and_Trackback_Actions

否则,如果您想保留该操作,您可以添加一个额外的字段或元数据,例如,deleted。当评论被删除时,如上所述:挂钩delete_comment 调用并将操作更新为deleted = true。然后,当您对所有操作运行查询时,排除已删除的语句,例如 ... WHERE deleted = NULL ... 等。

EDIT2:

要回答您的选择语句,可以使用以下方法:

SELECT * FROM myplugin_transactions 
LEFT JOIN myplugin_meta AS data1 
ON ( myplugin_transactions.id = data1.txn_id AND data1.key = 'data1' )
LEFT JOIN myplugin_meta AS data2 
ON ( myplugin_transactions.id = data2.txn_id AND data2.key = 'data2' )
WHERE data1.data = 'x'
AND data2.data = 'y'

显然将data1data2 关键字替换为有意义的描述。

【讨论】:

  • 感谢您对使用辅助表存储无限多的附加数据的想法。至于第二部分,我不想删除日志条目,而只是在满足某些条件时将其从用户的视图中隐藏起来,但是它们会混淆分页,因为如果有一个,我最终可能会在 10 个页面上有 9 个条目被过滤掉了。
  • 谢谢,这是一个非常好的建议。我已经编辑了关于如何根据建议的架构查询某些内容的问题。
  • 如果我想在查询中获取所有元数据怎么办?我必须做很多子查询吗?或者说显示日志表,是否需要对主表进行foreach循环,并根据类型分别查询元表?
  • 如果您想使用 SQL 通过元键进行过滤,您只需要加入表。如果您想要所有元数据,请单独查询所有元数据 (SELECT * FROM myplugin_meta WHERE txn_id = {$id})。现在,我认为您同时结合了很多问题,您可能想查看现有插件以了解它们是如何工作的,尝试构建您的插件,然后返回具体问题。
猜你喜欢
  • 2018-12-02
  • 2017-02-07
  • 2012-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-27
  • 1970-01-01
  • 2011-03-13
相关资源
最近更新 更多