如何在 Laravel 中实现模型修订?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18502697/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 08:20:53  来源:igfitidea点击:

How can I implement model revisions in Laravel?

phpmysqllaraveleloquentrevisionable

提问by Sayak Banerjee

This question is for my pastebin app written in PHP.

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

I did a bit of a research, although I wasn't able to find a solution that matches my needs. I have a table with this structure:

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

+-----------+------------------+------+-----+---------+----------------+
| 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       |                |
+-----------+------------------+------+-----+---------+----------------+

This is for a pastebin application. I basically want paste revisions so that if you open paste #1234, it shows all past revisions of that paste.

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

I thought of three ways:

我想到了三种方法:

Method 1

方法一

Have a revisions table with id and old_id or something and for each ID, I would insert all old revisions, so if my structure looks like this:

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

rev3: 1234
rev2: 1233
rev1: 1232

The table will contain this data:

该表将包含以下数据:

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

The problem which I have with this is that it introduces a lot of duplicate data. And the more the revisions get, it has not only more data but I need to do N inserts for each new paste to the revisions table which is not great for a large N.

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

Method 2

方法二

I can add a child_id to the paste table at the top and just update that. And then, when fetching the paste, I will keep querying the db for each child_id and their child_id and so on... But the problem is, that will introduce too many DB reads each time a paste with many revisions is opened.

我可以在顶部的粘贴表中添加一个 child_id 并更新它。然后,在获取粘贴时,我将继续查询每个 child_id 和它们的 child_id 等的数据库......但问题是,每次打开具有许多修订的粘贴时,都会引入过多的 DB 读取。

Method 3

方法三

Also involves a separate revisions table, but for the same scenario as method 1, it will store the data like this:

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

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

And when someone opens paste 1234, I'll use an IN clause to fetch all child paste data there.

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

Which is the best approach? Or is there a better approach? I am using Laravel 4 framework that has Eloquent ORM.

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

EDIT: Can I do method 1 with a oneToMany relationship? I understand that I can use Eager Loadingto fetch all the revisions, but how can I insert them without having to do a dirty hack?

编辑:我可以使用 oneToMany 关系执行方法 1 吗?我知道我可以使用Eager Loading来获取所有修订,但是如何插入它们而不必进行肮脏的黑客攻击?

EDIT: I figured out how to handle the above. I'll add an answer to close this question.

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

采纳答案by Sayak Banerjee

So here is what I am doing:

所以这就是我在做什么:

Say this is the revision flow:

说这是修订流程:

1232 -> 1233 -> 1234
1232 -> 1235

So here is what my revision table will look like:

所以这是我的修订表的样子:

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

IDs 2 and 3 show that when I open 1234, it should show both 1233 and 1232 as revisions on the list.

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

Now the implementation bit: I will have the Paste model have a one to many relationship with the Revision model.

现在是实现位:我将使 Paste 模型与 Revision 模型具有一对多的关系。

  • When I create a new revision for an existing paste, I will run a batch insert to add not only the current new_id and old_id pair, but pair the current new_id with all revisions that were associated with old_id.
  • When I open a paste - which I will do by querying new_id, I will essentially get all associated rows in the revisions table (using a function in the Paste model that defines hasMany('Revision', 'new_id')) and will display to the user.
  • 当我为现有粘贴创建新修订时,我将运行批量插入,不仅添加当前的 new_id 和 old_id 对,还将当前的 new_id 与与 old_id 关联的所有修订配对。
  • 当我打开一个粘贴时——我将通过查询 new_id 来完成,我将基本上获得修订表中的所有关联行(使用定义 hasMany('Revision', 'new_id') 的 Paste 模型中的函数)并将显示到用户。

I am also thinking about displaying the author of each revision in the "Revision history" section on the "view paste" page, so I think I'll also add an author column to the revision table so that I don't need to go back and query the main paste table to get the author.

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

So that's about it!

就是这样!

回答by Abishek

If you are on Laravel 4, give Revisionablea try. This might suite your needs

如果您使用的是 Laravel 4,请尝试Revisionable。这可能适合您的需求

回答by Francisco Corrales Morales

There are some great packages to help you keeping model revisions:

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

  • If you only want to keep the models revisions you can use:
  • 如果您只想保留模型修订,您可以使用:

Revisionable

可修改

  • If you also want to log any other actions, whenever you want, with custom data, you can use:
  • 如果您还想随时使用自定义数据记录任何其他操作,您可以使用:

Laravel Activity Logger

Laravel 活动记录器

Honorable mentions:

荣誉奖: