0

我一直在研究一个 CakePHP 3 项目,其中包含一些更复杂的部分,而且框架的官方文档似乎没有给我正在寻找的答案。需要做以下事情:

用户可以属于多个项目。在每个项目中,属于当前项目的每个用户都可以访问应用程序的不同部分,这由一个名为 Resources 的表处理,该表存储资源 ID。

所以简而言之,用户 A 可以访问项目 A 和项目 B 中不同数量的资源。

我设置了以下关联:

  1. 用户通过 UsersProjects 属于ToMany Projects
  2. 用户通过 UsersResources 属于ToMany Resources

在 users_resources -table 我有以下字段:

用户 ID | 资源 ID | 项目编号

project_id -field 被添加到表中以使用户的资源项目特定。

关联配置如下:

用户表:

        $this->belongsToMany('Resources', [
            'foreignKey' => 'user_id',
            'targetForeignKey' => 'resource_id',
            'joinTable' => 'users_resources',
            'through' => 'UsersResources'
        ]);

资源表:

        $this->belongsToMany('Users', [
            'foreignKey' => 'resource_id',
            'targetForeignKey' => 'user_id',
            'joinTable' => 'users_resources',
            'through' => 'UsersResources'
        ]);

用户资源表:

        $this->belongsTo('Users', [
            'foreignKey' => 'user_id',
            'joinType' => 'INNER'
        ]);

        $this->belongsTo('Resources', [
            'foreignKey' => 'resource_id',
            'joinType' => 'INNER'
        ]);

        $this->belongsTo('Projects', [
            'foreignKey' => 'project_id',
            'joinType' => 'INNER'
        ]);

在 UsersResourcesTable 类中还实现了一个 buildRules 函数来帮助数据完整性:

  public function buildRules(RulesChecker $rules)
    {
        $rules->add($rules->existsIn(['user_id'], 'Users'));
        $rules->add($rules->existsIn(['resource_id'], 'Resources'));
        $rules->add($rules->existsIn(['project_id'], 'Projects'));
        $rules->add($rules->isUnique(['user_id', 'resource_id', 'project_id']));
        return $rules;
    }

数据保存如下:

        $usersTable = TableRegistry::get('Users');
        $user = $usersTable->get(129);
        $data = [
            'resources' => [
                [
                    'id' => 48,
                    '_joinData' => [
                        'project_id' => 2
                    ]
                ]
            ]
        ];
        $user = $usersTable->patchEntity($user, $data, ['associated' => ['Resources']]);
        if ($usersTable->save($user)) {
            $this->out('success');
        } else {
            $this->out('fail');
        }

patchEntity后的实体数据:

   {
        "id": 129,
        "email": "john.doe@example.com",
        "created": null,
        "modified": "2016-02-05T20:50:06+0000",
        "firstname": "John",
        "lastname": "Doe",
        "type": 1,
        "resources": [
            {
                "id": 48,
                "type": "r",
                "_joinData": {
                    "project_id": 2
                }
            }
        ]
    }

当数据以项目 id 2 保存时,保存按预期工作。当我保存相同的数据但将项目 id 更改为 1 时(user_idresource_id将保持不变),项目 id 为 2 的前一行将从表中删除。期望的行为显然是旧记录将保留在表中。我注意到,尽管在 UsersTable 的资源关联定义中添加一个值为 'append' 的 saveStrategy-option 将使保存正确完成(不会删除 project_id 为 2 的行)。但是当我在使用附加策略时尝试保存现有记录时,保存将失败(保存结果为假)。

所以如果我使用替换策略,以前的数据会被删除,如果我使用追加策略,现有行的更新将导致蛋糕的错误。我认为由于唯一规则,在规则检查期间会引发错误。

我认为替换策略将是可行的方法,但似乎 project_id -field 值被忽略,并导致每当添加新行时将删除以前的数据(具有相同的 user_id 和 resource_id)不同的项目 ID。

所以我的问题是:

是否可以将第三个 id 字段添加到 belongsToMany-association 的槽表中,以便额外的字段也将被视为 id 字段,以便框架知道何时更新或插入记录到连接表?

这个想法是表中的所有三个字段都是唯一的。现在看来,框架丢弃了额外的字段,因此插入和更新无法按预期工作。或者数据库结构中是否存在需要修复的设计缺陷?

我宁愿坚持使用 CakePHP 约定,但似乎这种情况很难解决。任何指导表示赞赏!

4

0 回答 0