Silverstripe 4.7:如何让会员仅操作自身创建的DataObject
Silverstripe 4.7 实现会员仅操作自身创建的DataObject的正确方案
问题根源
创建新条目时,ProjectCatObject尚未写入数据库,OwnerID字段为空,此时canView()方法里的$member->ID == $this->OwnerID条件不成立;如果当前会员没有CMS_ACCESS_LeftAndMain权限,就会返回false,触发权限错误。
修正实现方案
1. 完善DataObject定义,规范关联关系
将直接存储OwnerID改为使用$has_one关联Member,更符合Silverstripe ORM规范:
class ProjectCatObject extends DataObject implements PermissionProvider { private static $db = [ // 你的其他字段 ]; private static $has_one = [ 'Owner' => Member::class ]; public function onBeforeWrite() { parent::onBeforeWrite(); // 仅当Owner未设置时,赋值当前登录用户 if (!$this->OwnerID && $member = Security::getCurrentUser()) { $this->OwnerID = $member->ID; } } // 实现PermissionProvider接口,定义基础权限 public function providePermissions() { return [ 'PROJECTCAT_VIEW' => '查看项目分类', 'PROJECTCAT_EDIT' => '编辑项目分类', 'PROJECTCAT_DELETE' => '删除项目分类', ]; } }
2. 修正canView、canEdit、canDelete方法
处理未保存的新对象(OwnerID为空)的权限逻辑,同时兼顾管理员权限:
public function canView($member = null) { // 优先使用传入的member参数,无则取当前登录用户 $member = $member ?: Security::getCurrentUser(); if (!$member) { return false; } // 拥有CMS后台访问权限的用户可查看所有条目 if (Permission::check('CMS_ACCESS_LeftAndMain', 'any', $member)) { return true; } // 未保存的新条目,允许创建者查看 if (!$this->OwnerID) { return true; } // 普通用户仅能查看自己创建的条目 return $member->ID == $this->OwnerID; } public function canEdit($member = null) { $member = $member ?: Security::getCurrentUser(); if (!$member) { return false; } if (Permission::check('CMS_ACCESS_LeftAndMain', 'any', $member)) { return true; } // 未保存的新条目,允许创建者编辑 if (!$this->OwnerID) { return true; } return $member->ID == $this->OwnerID; } public function canDelete($member = null) { $member = $member ?: Security::getCurrentUser(); if (!$member) { return false; } if (Permission::check('CMS_ACCESS_LeftAndMain', 'any', $member)) { return true; } return $member->ID == $this->OwnerID; }
3. CMS列表筛选优化(可选)
如果在CMS后台展示该DataObject列表,需添加筛选条件,让普通用户仅看到自己创建的条目:
// 在GridField配置中添加筛选逻辑 $gridField = GridField::create( 'ProjectCategories', '项目分类', // 仅展示当前用户的条目 ProjectCatObject::get()->filter('OwnerID', Security::getCurrentUser()->ID), GridFieldConfig_RecordEditor::create() );
关键注意点
- 不要忽略
$member参数:can*方法会主动传入member对象,直接使用比调用Security::getCurrentUser()更严谨(比如后台模拟用户操作场景)。 - 新对象权限处理:未保存的对象
OwnerID为空,必须允许创建者查看/编辑,否则创建后会立刻触发权限报错。 - 使用ORM关联:用
$has_one关联Member而非直接存储ID,便于后续扩展查询和维护。
内容的提问来源于stack exchange,提问作者seppzzz
相关产品推荐
相关产品推荐

