gpt4 book ai didi

silverstripe - 在 SilverStripe 中链接/取消链接多对多记录后更新字段

转载 作者:行者123 更新时间:2023-12-04 18:04:45 25 4
gpt4 key购买 nike

我创建了一个 Customer DataObject通过扩展 Member . Customer有一个 many_manyPackage 的数据关系DataObject .

我想增加/减少 Credits Customer 中的字段DataObject当一个 Package通过基于 Limit 的 CMS 链接/取消链接Package 中的字段 table 。

客户

class Customer extends Member {

private static $db = array(
'Gender' => 'Varchar(2)',
'DateOfBirth' => 'Date',
'Featured' => 'Boolean',
'Credits' => 'Int'
);

private static $many_many = array(
'Packages' => 'Package'
);

public function getCMSFields() {

$fields = new FieldList();

$config = GridFieldConfig_RelationEditor::create();
$config->removeComponentsByType('GridFieldAddNewButton');

$packageField = new GridField(
'Packages',
'Package',
$this->Packages(),
$config
);

$fields->addFieldToTab('Root.Package', $packageField);

Session::set('SingleID', $this->ID);

$this->extend('updateCMSFields', $fields);

return $fields;
}
}



class Package extends DataObject {

private static $db = array(
'Title' => 'Varchar(255)',
'Limit' => 'Int'
);

private static $belongs_many_many = array(
'Customers' => 'Customer'
);

}

最佳答案

当您创建或删除多对多关系时,只有一条记录在您的数据库中被修改 - 表中的一条记录连接关系双方的元素。因此,关系所基于的对象都不会更新。这就是为什么这样的方法:onBeforeWrite , onAfterWrite , onBeforeDeleteonAfterDelete根本不会被调用,你不能用它们来检测这种变化。

然而,Silverstripe 提供类 ManyManyList它负责与多对多关系相关的所有操作。有两种您感兴趣的方法:添加和删除。您可以覆盖它们并采取内部行动来做您需要的事情。无论对象类型是什么,这些方法显然都会在每个链接或取消链接操作上调用,因此您应该对您特别感兴趣的类进行一些过滤。

覆盖 ManyManyList 的正确方法class 是使用 Injector 机制,以免修改 framework 或 cms 文件夹内的任何内容。下面的示例使用 Silverstripe 中成员和组之间的关系,但您可以轻松地根据需要采用它(客户 -> 成员;包 -> 组)。

应用程序.yml

Injector:
ManyManyList:
class: ManyManyListExtended

ManyManyListExtended.php

/**
* When adding or removing elements on a many to many relationship
* neither side of the relationship is updated (written or deleted).
* SilverStripe does not provide any built-in actions to get information
* that such event occurs. This is why this class is created.
*
* When it is uses together with SilverStripe Injector mechanism it can provide
* additional actions to run on many-to-many relations (see: class ManyManyList).
*/
class ManyManyListExtended extends ManyManyList {

/**
* Overwritten method for adding new element to many-to-many relationship.
*
* This is called for all many-to-many relationships combinations.
* 'joinTable' field is used to make actions on specific relation only.
*
* @param mixed $item
* @param null $extraFields
* @throws Exception
*/
public function add($item, $extraFields = null) {
parent::add($item, $extraFields);

if ($this->isGroupMembershipChange()) {
$memberID = $this->getMembershipID($item, 'MemberID');
$groupID = $this->getMembershipID($item, 'GroupID');
SS_Log::log("Member ($memberID) added to Group ($groupID)", SS_Log::INFO);
// ... put some additional actions here
}
}

/**
* Overwritten method for removing item from many-to-many relationship.
*
* This is called for all many-to-many relationships combinations.
* 'joinTable' field is used to make actions on specific relation only.
*
* @param DataObject $item
*/
public function remove($item) {
parent::remove($item);

if ($this->isGroupMembershipChange()) {
$memberID = $this->getMembershipID($item, 'MemberID');
$groupID = $this->getMembershipID($item, 'GroupID');
SS_Log::log("Member ($memberID) removed from Group ($groupID)", SS_Log::INFO);
// ... put some additional actions here
}
}

/**
* Check if relationship is of Group-Member type.
*
* @return bool
*/
private function isGroupMembershipChange() {
return $this->getJoinTable() === 'Group_Members';
}

/**
* Get the actual ID for many-to-many relationship part - local or foreign key value.
*
* This works both ways: make action on a Member being element of a Group OR
* make action on a Group being part of a Member.
*
* @param DataObject|int $item
* @param string $keyName
* @return bool|null
*/
private function getMembershipID($item, $keyName) {
if ($this->getLocalKey() === $keyName)
return is_object($item) ? $item->ID : $item;
if ($this->getForeignKey() === $keyName)
return $this->getForeignID();
return false;
}
}

3dgoo 提供的解决方案也应该可以正常工作,但 IMO 代码会进行更多的“黑客攻击”,这就是为什么它的可维护性要低得多。它需要更多的修改(在两个类中),如果您想要进行任何额外的链接/取消链接管理,例如添加自定义管理模块或某些表单,则需要成倍增加。

关于silverstripe - 在 SilverStripe 中链接/取消链接多对多记录后更新字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32324867/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com