我已经在 DataObjects
上使用了版本控制当它们包含大量内容时,现在我想知道是否可以将版本控制应用于 many_many
关系?
假设我有以下内容:
class Page extends SiteTree
{
private static $many_many = array(
'Images' => 'Image'
);
}
然后 ORM 会创建一个
Page_Images
表供我存储关系。为了拥有版本化关系,需要更多的表(例如 Page_Images_Live
)。有没有办法告诉 ORM 创建版本化关系?当使用
Page * – * Images
查看上面的示例时关系,我不想要 Image
要版本化的类,而是关系。例如。像这样:Version Stage:
---
PageA
Images ( ImageA, ImageB, ImageC )
Version Live:
---
PageA
Images ( ImageA, ImageC, ImageD, ImageE )
这甚至可以开箱即用吗?
最佳答案
我花了很多时间研究这个,但没有从根本上修改 ManyManyList
(因为它没有通过扩展系统公开必要的钩子(Hook)),没有太多选择。
我是甜品第一的人,怎么办?
我完成这个壮举的唯一建议本质上是一个多对多的桥接对象(即一个单独的实体加入 Page
和 Image
)通过 $has_many
虽然它仍然需要相当多的修改。
这是 partially discussed on the forum其中通过将版本化项目存储在实际对象而不是连接表中来破坏实际关系的解决方案。那会奏效,但我认为我们仍然可以做得更好。
我个人倾向于将这种关系的版本与 Page
联系起来。本身和我下面的部分解决方案涵盖了这一点。阅读下面的折叠以获取更多信息,尝试将此作为对 ManyManyList
的更新.
像这样的事情是一个开始:
class PageImageVersion extends DataObject
{
private static $db = array(
'Version' => 'Int'
);
private static $has_one = array(
'Page' => 'Page',
'Image' => 'Image'
);
}
这包含我们的 2 向关系以及我们存储的版本号。您需要指定
getCMSFields
功能添加所需的正确字段,允许您将其与现有图像相关联或上传新图像。我避免覆盖这一点,因为与实际版本处理部分相比,它应该相对简单。现在,我们有一个
has_many
在 Page
像这样:private static $has_many = array(
'Images' => 'PageImageVersion'
);
在我的测试中,我还为
Image
添加了扩展名添加匹配 $has_many
也像这样:class ImageExtension extends DataExtension
{
private static $has_many = array(
'Pages' => 'PageImageVersion'
);
}
Honestly, not sure if this is necessary beyond adding the
Pages
function on theImage
side of the relationship. As far as I can see, it won't really matter for this particular usecase.
不幸的是,由于这种版本控制方式,我们不能使用调用
Images
的标准方式。 ,我们需要有点创意。像这样的东西:public function getVersionedImages($Version = null)
{
if ($Version == null)
{
$Version = $this->Version;
}
else if ($Version < 0)
{
$Version = max($this->Version - $Version, 1);
}
return $this->Images()->filter(array('Version' => $Version));
}
当您拨打
getVersionedImages()
,它将返回所有具有 Version
的图像设置它与当前页面的版本对齐。还支持通过 getVersionedImages(-1)
获取以前的版本对于最后一个版本,甚至通过传递任何位置编号来获取页面特定版本的图像。好的,到目前为止一切顺利。我们现在需要确保每个页面写入我们都会为这个新版本的页面获得一个重复的图像列表。
与
onAfterWrite
功能在 Page
, 我们可以完成这个:public function onAfterWrite()
{
$lastVersionImages = $this->getVersionedImages(-1);
foreach ($lastVersionImages as $image)
{
$duplicate = $image->duplicate(false);
$duplicate->Version = $this->Version;
$duplicate->write();
}
}
For those playing at home, this is where things get a bit iffy relating to how restoring previous versions of
Page
would affect this.
因为我们将在
GridField
中编辑它,我们需要做一些事情。首先是确保我们的代码可以处理 Add New
功能。我的想法是
onAfterWrite
在 PageImageVersion
目的:public function onAfterWrite()
{
//Make sure the version is actually saved
if ($this->Version == 0)
{
$this->Version = $this->Page()->Version;
$this->write();
}
}
让您的版本项目显示在
GridField
,你会像这样设置它:$gridFieldConfig = GridFieldConfig_RecordEditor::create();
$gridField = new GridField("Images", "Images", $this->getVersionedImages(), $gridFieldConfig);
$fields->addFieldToTab("Root.Images", $gridField);
您可能希望直接从
GridField
链接到图像。通过 GridFieldConfig_RelationEditor
然而,这是事情变得糟糕的时候。蔬菜的时间...
最大的困难之一是
GridField
,用于链接和取消链接这些实体。使用标准 GridFieldDeleteAction
没有正确的版本会直接更新关系。您将需要扩展
GridFieldDeleteAction
并覆盖 handleAction
写下您的 Page
对象(以触发另一个版本),为上一个版本复制我们版本化图像对象的每个版本,同时使其跳过新版本中您不想要的那个。I'll admit, this last bit is just guesswork by me. From my understanding and debugging, it should work but simply there is a lot of fiddling to get it right.
您的分机号
GridFieldDeleteAction
然后需要添加到您的特定 GridField
.这基本上是使此解决方案起作用的最后一步。一旦你完成了添加、删除、复制、版本更新的部分,这真的只是使用
getVersionedImages()
的问题。以获得正确的图像。结论
避免。 我明白你为什么要这样做,但我真的没有看到一种干净的方法来处理这个,而没有对如何进行适当的更新
many_many
关系在 Silverstripe 中处理。但我真的想要它作为
ManyManyList
!我认为
ManyManyList
所需的更改有一个 3 路 key (外键、本地 key 、版本 key )和用于添加/删除/获取等的各种方法更新。如果
add
中有钩子(Hook)和 remove
功能,您可以将功能作为扩展(通过 Silverstripe 的扩展系统)潜入,并将所需的数据添加到 many_many
的额外字段中。关系允许。虽然我可以通过扩展
ManyManyList
来实现这一点直接然后强制ManyManyList
将通过 Object::useCustomClass
替换为我的自定义类,这将是一个更困惑的解决方案。对我来说,对一个纯粹的
ManyManyList
给出完整的答案实在是太长/太复杂了。在这个阶段的解决方案(尽管我稍后可能会回到这个问题并试一试)。免责声明:我不是 Silverstripe Core 开发人员,这整个事情可能有一个更简洁的解决方案,但我根本看不到如何解决。
关于silverstripe - 是否可以对 many_many 关系进行版本控制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17896869/