链接/取消链接SilverStripe中的多条记录后更新字段
我通过扩展链接/取消链接SilverStripe中的多条记录后更新字段,silverstripe,Silverstripe,我通过扩展成员创建了一个客户数据对象客户与包数据对象有多个数据关系 当根据包表中的限制字段,通过CMS链接/取消链接包时,我希望增加/减少客户数据对象中的积分字段 客户 class客户扩展成员{ 私有静态$db=array( “性别”=>“Varchar(2)”, “出生日期”=>“日期”, '特色'=>'布尔', “积分”=>“整数” ); 私有静态$many\u many=数组( “包”=>“包” ); 公共函数getCMSFields(){ $fields=新字段列表(); $config
成员
创建了一个客户
数据对象
<代码>客户与包
数据对象
有多个
数据关系
当根据包
表中的限制
字段,通过CMS链接/取消链接包
时,我希望增加/减少客户
数据对象
中的积分
字段
客户
class客户扩展成员{
私有静态$db=array(
“性别”=>“Varchar(2)”,
“出生日期”=>“日期”,
'特色'=>'布尔',
“积分”=>“整数”
);
私有静态$many\u many=数组(
“包”=>“包”
);
公共函数getCMSFields(){
$fields=新字段列表();
$config=GridFieldConfig_RelationEditor::create();
$config->removeComponentsByType('GridFieldAddNewButton');
$packageField=新网格字段(
"包裹",,
“包”,
$this->Packages(),
$config
);
$fields->addFieldToTab('Root.Package',$packageField);
会话::set('SingleID',$this->ID);
$this->extend('updateCMSFields',$fields);
返回$fields;
}
}
套餐
类包扩展了DataObject{
私有静态$db=array(
'Title'=>'Varchar(255)',
'限制'=>'整数'
);
private static$properties\u many\u many=数组(
“客户”=>“客户”
);
}
注意:没有实际检查模型是否工作,但通过目视检查,这将有助于您:
在您提供的链接上,您正在使用
$customer = Customer::get()->Filter...
它返回对象的数据列表,而不是单个对象,除非您从数据列表中指定所需的对象
如果要筛选客户,则需要从数据列表中获取特定客户,例如本例中的第一个客户
$customer = Customer::get()->filter(array('ID' => $this->CustomerID))->first();
但您应该能够通过以下方式获得单一数据对象:
$customer = $this->Customer();
当您将客户定义为“has_one”时。如果关系是一个Has-many,那么使用()将获得对象的数据列表
Protip:
您不需要在SilverStripe中编写我们自己的调试文件。它有自己的功能。例如Debug::log(“yay”)代码>将输出写入文件的内容,以及将其直接转储出去的Debug::dump(“yay”)
提示:您可以检查您正确访问的对象是什么<代码>调试::转储(get_类($customer))代码>将仅输出对象的类 问题在于在多对多关系中添加或删除项目时,关系的任何一方都不会写入。因此,在这两个对象上都不会调用onAfterWrite
和onbeforewite
我以前遇到过这个问题。我使用的解决方案不是很好,但它是唯一对我有效的方法
我们可以做的是在调用getCMSFields
时将包的ID列表设置为会话变量。然后,当在网格字段中添加或删除项目时,我们刷新CMS面板,再次调用getCMSFields
。然后检索上一个列表并将其与当前列表进行比较。如果清单不一样,我们可以做点什么
客户
class客户扩展成员{
// ...
公共函数getCMSFields(){
//每次添加或删除包时,一些JavaScript将重新加载面板
要求::javascript('/mysite/javascript/cms customer.js');
//这是保存包id列表并检查是否进行了任何更改的代码块
如果($this->ID){
if(Session::get($this->ID.'CustomerPackages')){
$initialCustomerPackages=json_decode(Session::get($this->ID.'CustomerPackages'),true);
$currentCustomerPackages=$this->Packages()->getIDList();
//检查包列表是否已更改
如果($initialCustomerPackages!=$currentCustomerPackages){
//在这里,你可以把你的代码放在你需要的地方
}
}
会话::set($this->ID.'CustomerPackages',json_encode($this->Packages()->getIDList());
}
$fields=parent::getCMSFields();
$config=GridFieldConfig_RelationEditor::create();
$config->removeComponentsByType('GridFieldAddNewButton');
$packageField=GridField::create(
"包裹",,
“包”,
$this->Packages(),
$config
);
//需要添加此类,以便调用我们的javascript
$packageField->addExtraClass('refresh-on-reload');
$fields->addFieldToTab('Root.Package',$packageField);
会话::set('SingleID',$this->ID);
$this->extend('updateCMSFields',$fields);
返回$fields;
}
}
if($this->ID){…}
代码块是所有会话代码发生的地方。还要注意,我们向网格字段中添加了一个类,这样JavaScript刷新就可以工作了$packageField->addExtraClass('refresh-on-reload')代码>
如前所述,每次从列表中添加或删除包时,我们都需要添加一些JavaScript来重新加载面板
cms customer.js
(function($) {
$.entwine('ss', function($){
$('.ss-gridfield.refresh-on-reload').entwine({
reload: function(e) {
this._super(e);
$('.cms-content').addClass('loading');
$('.cms-container').loadPanel(location.href, null, null, true);
}
});
});
})(jQuery);
在if($initialCustomerPackages!=$currentCustomerPackages){…}
code块中,您可以执行许多操作
您可以使用$this->Packages()
获取与此客户关联的所有当前包
您可以调用array\u diff
和array\u merge
仅获取已添加和删除的包:
$changedPackageIDs = array_merge(array_diff($initialCustomerPackages, $currentCustomerPackages), array_diff($currentCustomerPackages, $initialCustomerPackages));
$changedPackages = Package::get()->byIDs($changedPackageIDs);
上述代码将此功能添加到关系的客户
端
Injector:
ManyManyList:
class: ManyManyListExtended