You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 04:10:35