SilverStripe 4中如何编辑many_many_extraFields并在GridField编辑Data字段
在SilverStripe 4的多对多关联中编辑额外Data字段的方法
你已经搞定了多对多关联和排序功能,现在要在GridField里显示并编辑那个Data额外字段对吧?其实只需要调整GridField的配置,添加可编辑列组件或者自定义编辑弹窗就能实现。下面给你两种常用的方案:
方案一:在GridField列表内直接编辑Data字段
这种方式让用户可以在列表里直接修改Data值,不用跳转弹窗,操作更快捷。修改你的GridField配置代码如下:
$features = Feature::get(); $searchFeaturesButton = new GridFieldAddExistingSearchButton(); $searchFeaturesButton->setSearchList($features); $featureConfig = GridFieldConfig_RelationEditor::create(); // 移除不需要的组件,编辑按钮可以去掉,因为我们用列表内编辑 $featureConfig->removeComponentsByType([ GridFieldAddExistingAutocompleter::class, GridFieldAddNewButton::class, GridFieldEditButton::class ]); // 添加可编辑列组件,配置显示和编辑的字段 $editableColumns = new GridFieldEditableColumns(); $editableColumns->setDisplayFields([ 'Title' => [ 'title' => 'Feature Name', 'field' => ReadonlyField::class // Feature的标题设为只读,只允许编辑Data ], 'Data' => [ 'title' => 'Custom Data', 'field' => TextField::class, // 回调处理多对多额外字段的读写逻辑 'callback' => function($item, $column, $grid) { // 获取当前关联的中间表数据 $extraData = $grid->getRelationHandler()->getExtraData($item); // 创建TextField并设置当前值 $field = TextField::create($column, 'Custom Data') ->setValue($extraData->Data); // 设置字段名称,确保保存时能正确映射到中间表 $field->setName(sprintf('%s[%s][%s]', $grid->getName(), $item->ID, $column)); return $field; } ] ]); $featureConfig->addComponent($editableColumns); // 指定排序字段为你定义的SortOrder $featureConfig->addComponent(new GridFieldOrderableRows('SortOrder')); $featureConfig->addComponent($searchFeaturesButton); $featureGrid = GridField::create('Features', 'Features', $this->Features(), $featureConfig); $field->addFieldToTab('Root.Main', $featureGrid);
方案二:通过弹窗编辑Data字段
如果你更习惯用弹窗编辑的方式(和默认的RelationEditor行为一致),可以保留编辑按钮,然后自定义弹窗里的表单:
$features = Feature::get(); $searchFeaturesButton = new GridFieldAddExistingSearchButton(); $searchFeaturesButton->setSearchList($features); $featureConfig = GridFieldConfig_RelationEditor::create(); $featureConfig->removeComponentsByType([ GridFieldAddExistingAutocompleter::class, GridFieldAddNewButton::class ]); // 注意不要移除GridFieldEditButton,这样才能打开编辑弹窗 // 获取详情表单组件,自定义编辑内容 $detailForm = $featureConfig->getComponentByType(GridFieldDetailForm::class); $detailForm->setItemEditFormCallback(function($form, $item) use ($featureConfig) { $gridField = $featureConfig->getGridField(); $relationHandler = $gridField->getRelationHandler(); // 获取当前关联的中间表数据 $extraData = $relationHandler->getExtraData($item); // 把Data字段添加到编辑表单 $form->Fields()->addFieldsToTab('Root.Main', [ TextField::create('Data', 'Custom Data') ->setValue($extraData->Data) ]); // 添加保存回调,确保Data值能保存到中间表 $form->setSaveCallback(function($form, $item) use ($relationHandler) { $data = $form->getData(); if (isset($data['Data'])) { $relationHandler->setExtraData($item, ['Data' => $data['Data']]); } return $item; }); return $form; }); $featureConfig->addComponent(new GridFieldOrderableRows('SortOrder')); $featureConfig->addComponent($searchFeaturesButton); $featureGrid = GridField::create('Features', 'Features', $this->Features(), $featureConfig); $field->addFieldToTab('Root.Main', $featureGrid);
关键说明
- 多对多的额外字段存在自动生成的中间关联表里,所以不能直接通过
Feature或Model对象读写,必须用GridFieldRelationHandler来操作这些字段 - 两种方案都能实现编辑功能,你可以根据自己的后台交互偏好选择
- 测试的时候记得保存后查看数据库的中间表,确认
Data字段的值是否正确存储
内容的提问来源于stack exchange,提问作者Zubair
相关产品推荐
相关产品推荐

