Silverstripe 4 新建BlogPost时如何默认添加many_many关联
实现方案
可以通过两种方式搭配实现你要的默认关联效果,覆盖所有创建场景同时保证后台编辑体验:
1. 写入逻辑兜底(必选,全场景生效)
在你为BlogPost编写的扩展类中添加onAfterWrite钩子,对象首次写入数据库时自动关联当前子站点,不管是后台创建、前端投稿还是脚本生成内容都会生效:
// 扩展类内添加标记位,避免重复执行关联逻辑 protected bool $defaultSubsiteApplied = false; public function onAfterWrite() { parent::onAfterWrite(); // 仅首次写入、未应用过默认关联时执行 if (!$this->defaultSubsiteApplied) { $currentSubsiteId = SubsiteState::singleton()->getSubsiteId(); $currentSubsite = Subsite::get_by_id($currentSubsiteId); // 校验当前子站点存在,且关联列表中还没加入该子站 if ($currentSubsite?->exists() && !$this->owner->Subsites()->byID($currentSubsiteId)) { $this->owner->Subsites()->add($currentSubsite); } $this->defaultSubsiteApplied = true; } }
2. 表单默认值优化(可选,提升后台体验)
如果希望管理员打开新建BlogPost页面时,TagField就默认选中当前子站点(而不是保存后才自动关联),可以修改你原来的字段配置,新建对象时把当前子站点传入作为默认选中项:
$currentSubsite = Subsite::get_by_id(SubsiteState::singleton()->getSubsiteId()); $defaultSubsites = $this->owner->isInDB() ? $this->owner->Subsites() : ($currentSubsite?->exists() ? ArrayList::create([$currentSubsite]) : ArrayList::create()); $fields->addFieldToTab('Root.PostOptions', TagField::create('Subsites','Show on other sites', Subsite::get(), $defaultSubsites) ->setShouldLazyLoad(false) ->setCanCreate(false) );
补充说明
- 上述逻辑不会强制绑定当前子站点,管理员保存时手动取消选中当前子站点的操作会正常生效
- 如果需要强制所有BlogPost必须关联创建时的子站点,可去掉
$defaultSubsiteApplied的单次执行限制,每次写入都检查当前子站是否在关联列表中,不存在就自动补上,同时可在表单字段中把当前子站点设为禁用状态不允许取消选中
内容的提问来源于stack exchange,提问作者galilee
相关产品推荐
相关产品推荐

