【问题标题】:How can I implement model revisions in Laravel?如何在 Laravel 中实现模型修订?
【发布时间】:2013-08-29 05:08:52
【问题描述】:

这个问题是针对我用 PHP 编写的 pastebin 应用程序。

我做了一些研究,尽管我无法找到符合我需求的解决方案。我有一个具有这种结构的表:

+-----------+------------------+------+-----+---------+----------------+
| Field     | Type             | Null | Key | Default | Extra          |
+-----------+------------------+------+-----+---------+----------------+
| id        | int(12) unsigned | NO   | PRI | NULL    | auto_increment |
| author    | varchar(50)      | YES  |     |         |                |
| authorid  | int(12) unsigned | YES  |     | NULL    |                |
| project   | varchar(50)      | YES  |     |         |                |
| timestamp | int(11) unsigned | NO   |     | NULL    |                |
| expire    | int(11) unsigned | NO   |     | NULL    |                |
| title     | varchar(25)      | YES  |     |         |                |
| data      | longtext         | NO   |     | NULL    |                |
| language  | varchar(50)      | NO   |     | php     |                |
| password  | varchar(60)      | NO   |     | NULL    |                |
| salt      | varchar(5)       | NO   |     | NULL    |                |
| private   | tinyint(1)       | NO   |     | 0       |                |
| hash      | varchar(12)      | NO   |     | NULL    |                |
| ip        | varchar(50)      | NO   |     | NULL    |                |
| urlkey    | varchar(8)       | YES  | MUL |         |                |
| hits      | int(11)          | NO   |     | 0       |                |
+-----------+------------------+------+-----+---------+----------------+

这是一个 pastebin 应用程序。我基本上想要粘贴修订,因此如果您打开粘贴 #1234,它会显示该粘贴的所有过去修订。

我想到了三种方法:

方法一

有一个带有 id 和 old_id 之类的修订表,对于每个 ID,我会插入所有旧修订,所以如果我的结构如下所示:

rev3: 1234
rev2: 1233
rev1: 1232

该表将包含以下数据:

+-------+----------+
| id    | old_id   |
+-------+----------+
| 1234  | 1233     |
| 1234  | 1232     |
| 1233  | 1232     |
+-------+----------+

我遇到的问题是它引入了很多重复数据。而且修订越多,它不仅有更多的数据,而且我需要为每个新粘贴到修订表做 N 次插入,这对于大 N 来说并不是很好。

方法二

我可以在顶部的粘贴表中添加一个 child_id 并对其进行更新。然后,在获取粘贴时,我将继续查询数据库中的每个 child_id 及其 child_id 等等……但问题是,每次打开带有许多修订的粘贴时,都会引入太多的数据库读取。

方法3

还涉及到一个单独的修订表,但是对于与方法1相同的场景,它会像这样存储数据:

+-------+-----------------+
| id    | old_id          |
+-------+-----------------+
| 1234  | 1233,1232       |
| 1233  | 1232            |
+-------+-----------------+

当有人打开粘贴 1234 时,我将使用 IN 子句来获取那里的所有子粘贴数据。

哪种方法最好?还是有更好的方法?我正在使用具有 Eloquent ORM 的 Laravel 4 框架。

编辑:我可以使用 oneToMany 关系执行方法 1 吗?我知道我可以使用Eager Loading 来获取所有的修订,但是我怎样才能插入它们而不必进行肮脏的破解呢?

编辑:我想出了如何处理上述问题。我将添加一个答案来结束这个问题。

【问题讨论】:

  • 我将推荐方法 1 的修改。 ID 应为unique。并在其他表中添加修订。
  • 修订存储是树状结构还是线性结构?
  • 假设1232是原始的,1233对1232添加一些更改,1234对1232添加一些更改。然后,有人直接将更改添加到1232而不经过1234(称为1235)。你想怎么处理这个案子?
  • 这适用于哪个 Laravel 版本?
  • @invisal:同样的方式。如果 1235 是 1232 的新修订版,则 id 将为 1235,old_id 将为 1232。所以当我获取 1235 时,它只会显示 1232 作为修订版。

标签: php mysql laravel eloquent revisionable


【解决方案1】:

如果你在 Laravel 4 上,试试Revisionable。这可能适合您的需求

【讨论】:

  • 谢谢,是的,我在 L4,让我试试这个。 :)
  • 好吧,虽然这是一个很好的解决方案,但它将数据存储为 old_value 和 new_value,因此我将始终拥有两个 new_value 副本,一个在我的主表中,一个在修订表中。我想我最终可能会编写自己的版本控制系统:(
【解决方案2】:

这就是我正在做的事情:

说这是修订流程:

1232 -> 1233 -> 1234
1232 -> 1235

这就是我的修订表的样子:

+----+--------+--------+
| id | new_id | old_id |
+----+--------+--------+
| 1  | 1233   | 1232   |
| 2  | 1234   | 1233   |
| 3  | 1234   | 1232   |
| 4  | 1235   | 1232   |
+----+--------+--------+

ID 2 和 3 显示,当我打开 1234 时,它应该将 1233 和 1232 显示为列表中的修订版本。

现在实现位:我将让 Paste 模型与 Revision 模型建立一对多的关系。

  • 当我为现有粘贴创建新修订时,我将运行批量插入以添加当前 new_id 和 old_id 对,并将当前 new_id 与与 old_id 关联的所有修订配对。
  • 当我打开一个粘贴时 - 我将通过查询 new_id 来完成,我基本上会在修订表中获取所有关联的行(使用粘贴模型中定义 hasMany('Revision', 'new_id') 的函数)和将显示给用户。

我也在考虑在“查看粘贴”页面的“修订历史”部分显示每个修订的作者,所以我想我也会在修订表中添加一个作者列,这样我就不会需要返回主粘贴表查询获取作者。

就是这样!

【讨论】:

  • 简单查询主表时,如何区分同一数据的当前版本和旧版本?
  • @SebBarre 我从来没有遇到过修订表指向两个相同条目的情况。那是因为我将新(发布的)数据的 crc32 哈希值与上一个修订版进行了比较,并且仅当数据不同时才创建新修订版。见:github.com/sayakb/sticky-notes/blob/master/app/controllers/…
【解决方案3】:

有一些很棒的软件包可以帮助您保持模型修订:

  • 如果您只想保留可以使用的模型版本:

Revisionable

  • 如果您还想随时使用自定义数据记录任何其他操作,您可以使用:

Laravel Activity Logger

荣誉奖:

【讨论】:

    猜你喜欢
    • 2016-02-28
    • 2018-10-30
    • 2017-10-13
    • 2013-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-06
    • 2016-01-07
    相关资源
    最近更新 更多