如何保存修改以便以后申请?

时间:2013-12-01 12:51:54

标签: php database

我的webapp的主持人可以修改数据库中的某些数据。所有用户都可以看到这些修改。但出于某些原因,我不希望它们立即应用,而是仅在特定操作后 ,例如,当我明确接受时。时间表是:

  1. 表格中的字段的值为PreviousValue
  2. 主持人要求此值为NewValue。所有用户继续看到值PreviousValue
  3. 我接受更改。
    所有用户现在都会看到值NewValue
  4. 问题是版主可以修改大量表格中的字段。处理这个临时值的最佳方法是什么?我可以想象这些解决方案,但没有一个听起来不错:

    • 复制所有表格(合在一起MyTableMyTable_ToApply)。
    • 添加一个包含四个字段的特殊表(ToApplyTable):要修改的表,要修改的字段,要修改的条目的ID以及要应用的新值。

    你有更好的想法吗?

10 个答案:

答案 0 :(得分:4)

一旦问题相当广泛(并且可以有很多好的答案) - 这不是答案,而是另一种可能的解决方案:

您可以拥有以下表格:

id - just autogenerated number
datetime - date of change
changed_by - string with name of actor or id of some user
oldvalue - just old value
newvalue - just new value
update_insert_sql - here you put actual SQL which should be executed (you already have this sql in your current code)
state - 0 - it is not applied to db, 1 - already executed, 2 - you're rejected this change
datetime_of_apply - just date of action
datetime_of_reject - just date of action

注意:您可以存储SQL以获取当前值,而不是存储旧值,当不同版主对同一行/列进行多次更改时,这将对您有所帮助

因此,在您的界面中,您将能够看到所有表的所有建议更改,仅查看实际值和建议的新值,并在需要时更新数据库

可能的补充:要填充此表,您可以使用触发器,而不是更改当前代码

答案 1 :(得分:3)

这就是wordpress处理这些东西的方式。您可以在同一个表中,一个已发布的帖子,然后,作为新行,由不同的作者创建的未发布的修订集合,在不同的时刻创建,当然也与主帖相关联。

<强>更新

例如,如果您使用doctrine,您只需要相同的存储库和一个需要考虑的字段,例如:$rep->findByPublished(1)所有其余代码保持不变,因此您的控制器不了解业务 - 等级逻辑是否适度,并且不需要处理它。然后在管理员控制器中编写逻辑以将修订设置为主要帖子,并在接受修订时取消发布旧版本。简单,干净,可扩展,可维护和有效的模型。

CREATE TABLE `wp_posts` (
  `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,

  `post_author` bigint(20) unsigned NOT NULL DEFAULT '0',

   `post_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', #date of creation of this post o revision




  `post_status` varchar(20) NOT NULL DEFAULT 'publish', #publish, unpublish, 

  `post_name` varchar(200) NOT NULL DEFAULT '', #internal name if you want to better identify revisions

  `post_modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', #date of modification of this current post or revision

  `post_parent` bigint(20) unsigned NOT NULL DEFAULT '0', #if this is a revision, here you have the id of the main post this could replace if it it approved

  `post_type` varchar(20) NOT NULL DEFAULT 'post', //basicaly in your case, post or revision, but you can remove this one, since you can check if post_parent is 0 (or NULL if you want)


  ##Other columns with all the post information 



  PRIMARY KEY (`ID`),

) 

我不喜欢wordpress是如何制作的,但我不得不说这是一个很好的方法。而且,四个肯定:

  • 甚至不考虑有额外的列,因为你可以保存太少的元数据,如果你决定其他一些列可以被编辑,也必须修改数据库。
  • 在同一个字段中没有多个修订版。这违反了所有关系数据库原则。您可以为某些元数据编制序列化信息,在某些情况下可能没问题,但对于这是主要信息,在许多情况下处理和解析将是不可能的。
  • 你可以有一个帮助表,模型是有效的,但搜索,排序会更难,实际上你会有两个完全相同的表,所以这不是最好的主意。

答案 2 :(得分:3)

更新发生时,创建一个新行并拥有一个主持人需要查看的标志。主持人接受时,将接受的记录标记为活动,将前一记录标记为非活动。在最高级别执行此操作,以便在其他表连接时,它们将继承活动/非活动状态和is_moderated标志。

id | text      | is_active | is_moderated | is_accepted
-------------------------------------------------------
1  | hello     | 1         | 1            | 1             <-- This is the active row

添加新记录改变你好再见

id | text      | is_active | is_moderated | is_accepted
-------------------------------------------------------
1  | hello     | 1         | 1            | 1             <-- This is still the active row
2  | goodbye   | 0         | 0            | 0             <-- Moderator needs to accept or deny this

接受的结果:

id | text      | is_active | is_moderated | is_accepted
-------------------------------------------------------
1  | hello     | 0         | 1            | 1             <-- This is NOT the active row
2  | goodbye   | 1         | 1            | 1             <-- Accepted, new active row

拒绝国家:

id | text      | is_active | is_moderated | is_accepted
-------------------------------------------------------
1  | hello     | 1         | 1            | 1             <-- This is still the active row
2  | goodbye   | 0         | 1            | 0             <-- Moderator denied

您选择的查询将变为:

获取活动行:

SELECT * FROM TABLENAME WHERE is_active = 1

要获得需要审核的行

SELECT * FROM TABLENAME WHERE is_moderated = 0

答案 3 :(得分:3)

实际上,答案并不那么困难。这是我的想法: -

第1步: 只需在表Posts(或包含用户的完整帖子的表)中添加一列名为Moderated Post的列。任何主持人的任何审核或编辑都会进入本专栏。

第2步: 将另一列添加到名为Posts的表isModerated中。它包含值10,就像布尔值truefalse一样。

第3步:现在,你差不多完成了。你有一张这样的桌子: -

                      TABLE `POSTS`

| Post id | Initial Post | Moderated Post | isModerated |
_________________________________________________________
          | The first    |                |             |
|    1    | post goes    |                |      0      |
|         | here         |                |             |
_________________________________________________________
|         | The second   | The moderated  |             |
|    2    | post goes    | post goes here |      0      |
|         | here         |(Post invisible)|             |
_________________________________________________________
|         | The third    | The moderated  |             |
|    3    | post goes    | post goes here |      1      |
|         | here         | (Post visible) |             |
_________________________________________________________

现在在你的PHP代码中,在从表中检索所有值后,你会像这样显示你的帖子(只是一个粗略的草图): -

<?php 
if($isModerated == 1) { 
   echo $moderated_post; 
}else {
   echo $initial_post;
}
?>

对于众多表中的更改

正如您所说,审核会更改多个表中的值,为此您必须添加列Moderated_Value1)xn 其中n表示其值可以为的列数改变。示例: -

| Value 1 | Value 2 | Moderated_Value1 | Moderated_Value2 |
|   0     |    1    |      1000        |     2000         |

现在,您的代码变为: -

<?php 
if($isModerated == 1) { 
   echo $moderated_post; 
   echo $moderated_value1;
   echo $moderated_value2;
}else {
   echo $initial_post;
   echo value1;
   echo value2;
}
?>

使用此方法,还有一个优点,即您可以通过将表中的isModerated值从1更改为0来轻松回滚审核

答案 4 :(得分:2)

想法:为所有表添加修订号。当有人进行更改时,此更改的唯一修订号将存储在所有受影响的行中。而不是更新,插入具有更高版本号和相同ID的行。当然,Id列不能设置为唯一。当前活动的修订号存储在仅保存此编号的表中。然后生成看起来像前面的表的DB视图,但如果2行具有相同的id,则它只获得具有与活动修订版相等或更低的最高版本号的条目。在您的应用中,您使用视图而不是原始表。 然后,您可以查看原始表中的更改,删除不接受的更改,并提升当前活动的修订以接受尚未删除的所有更改。

答案 5 :(得分:2)

您可以为表添加修订并拥有复合主键

假设您有此表

id -> Integer PK
comment -> text
user -> integer

如果添加此字段

revision -> integer PK with id
published -> boolean -- this will tell you wich one is active

您可以添加更多审核字段,例如某些日期以检查创建新修订的时间或创建修订的人员

并且登录获取版本很简单,您可以通过其版本号选择任何修订版,或者您可以获得活动版...

当然,这会给你一些麻烦的问题(2个人同时修改同一行...但你可以使用信号量,或类似的东西),你不能继续使用发电机/自动补偿你的insert,(好吧,你只能使用生成器来获取新记录)。

另一种方式是,如果您不想存储所有更改历史记录,并且只需要最后一个版本,则添加文本字段,并使用编辑的值保存序列化数组,并且当您批准时,只需运行更新字段。

有很多方法,你可以使用这个序列化的aproch并使用aux表来保存历史记录,并混合aproche,在aux表中放入原点id,修订版和序列化数组,然后你同时拥有......所有版本的序列化版本......

选择最能描述你情况的人......

答案 6 :(得分:1)

另一个想法是将所有已更改的数据存储在一个数组中(array [$ table] [$ field] [$ id] = $ value),然后将其存储在一个带有TEXT类型字段的简单表中,采用json编码。这样,您还可以灵活地更改(添加)其他控件,而无需更改编辑表结构。 : - )

答案 7 :(得分:1)

我认为如果您认为没有任何 GOOD 选择,您可以轻松地向后工作并找出最差选项以查看最不好的选择。每个选择都需要牺牲。但是有什么牺牲?

选项#1 :复制所有表格(将MyTable和MyTable_ToApply放在一起)。

IMO这将是一个巨大的头痛。谈论太多的领域!您还需要创建额外的编码,以便将数据从一个表移动到另一个表。我认为这里有太多可能出错的地方。

选项#2 :添加一个包含四个字段的特殊表(ToApplyTable):要修改的表,要修改的字段,要修改的条目的ID以及新值申请。

我认为这也是一个肮脏的选项,正如你所提到的,因为同样的事情 - 将值从一个表移动到另一个表。

选项#3 :将dateismoderated值添加到表格中。

许多人都提到过这一点。你的论点是它太多(通常是无用的)列。我认为这比其他任何提到的要好。我将谦卑地提出一个最终方法,它是选项#1和选项#3的组合。

选项#4 :在每个可以拥有审核字段的表下创建自定义ismoderated表。

我在我的数据库中执行类似的操作并使用命名标准[TABLENAME]__ismoderated。在此表中,如果只需要一个列,则实际上不需要多个列。您可以在此需要审核的项目表中使用外键,然后在最终审核后删除该密钥。或者,您可以在此处添加主持人的用户ID,并在需要时添加作为附加字段的时间。

我个人认为我也会使用datetime字段,因此您可以跟踪更改并知道哪一个是最新的。

无论如何,这使您能够INNER JOIN两个表。如果您只想查看要审核的值。

答案 8 :(得分:1)

已经给出了很多答案,我觉得大多数都是非常合理的。我相信有一些很好的方法可以做到这一点。

我假设处理能力/速度比HDD和RAM中的存储空间更重要/更昂贵。 我也同意Robbes先生(我上面的某个地方)每行/单元应该有一个修订版,并且添加额外的列不是正确的解决方案(参见下面的详细说明)

让我首先从我认为不正确的选项开始:

  • JS​​ON / NOSQL。您的数据显然是关系型的。 (我的)SQL是通往的方式 走。
  • 存储为数组或其他形式的应用程序内存。该 这创造了开销,包括每个玩家的负担都没有 值得。此外,您希望能够存储这些,并重温这些 及时修订,并将其作为应用程序堆栈的一部分 随着时间的推移。这根本不值得。
  • 添加一个或多个添加到每个表的列。 创建的更改可以存储在那里。如你所说,这创造了一个 表中的大量开销是一种不好的做法。但是,这是一个适当的解决方案,例如,只需要编辑帖子或任何其他单个实体,并且不需要保存历史记录。但是,在这个问题中并非如此。

查看问题中给出的事实:

  1. 有一个或多个表格,其中包含可以审核的项目
  2. 有多个版主可以创建多个版本
  3. 这些修订并不总是按时间顺序应用
  4. 您可能希望记录所有建议和应用的记录
  5. 我认为您提供的第二个解决方案最适合您的数据。

    • 为修订创建单独的表。这是执行此操作的最佳规范化方式。根据审核的规模,您可以保留正在编辑的完整行的副本,也可以引用正在编辑的特定单元格。
    • 对于额外的专家级别点,您可以使用视图或临时表之类的内容来创建包含所有明确行的表,而不显示任何待处理或已拒绝的修订。这可以提高速度,但确实依赖于严谨的数据库工程。不是你想搞砸的东西

    可以通过多种方式对用户进行修订。使用上面的临时表/视图,您使用存储过程来更改表中的内容(或将单元格设置为“活动”并更新临时表/视图) 您可以简单地用新的行替换数据库中的行(虽然更新很昂贵),或者使用连接构造。

    如果CPU比存储便宜,那么查看具有哈希值的类似git的系统可能会有效。

答案 9 :(得分:0)

然而,主持人将使用表格更改数据..

当他们更改数据时,为什么不将数据保存在csv文件中...

修改更改时,可以插入实际表格中。

它只是一个想法..