我一直在研究一个 CakePHP 3 项目,其中包含一些更复杂的部分,而且框架的官方文档似乎没有给我正在寻找的答案。需要做以下事情:
用户可以属于多个项目。在每个项目中,属于当前项目的每个用户都可以访问应用程序的不同部分,这由一个名为 Resources 的表处理,该表存储资源 ID。
所以简而言之,用户 A 可以访问项目 A 和项目 B 中不同数量的资源。
我设置了以下关联:
- 用户通过 UsersProjects 属于ToMany Projects
- 用户通过 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_id和resource_id将保持不变),项目 id 为 2 的前一行将从表中删除。期望的行为显然是旧记录将保留在表中。我注意到,尽管在 UsersTable 的资源关联定义中添加一个值为 'append' 的 saveStrategy-option 将使保存正确完成(不会删除 project_id 为 2 的行)。但是当我在使用附加策略时尝试保存现有记录时,保存将失败(保存结果为假)。
所以如果我使用替换策略,以前的数据会被删除,如果我使用追加策略,现有行的更新将导致蛋糕的错误。我认为由于唯一规则,在规则检查期间会引发错误。
我认为替换策略将是可行的方法,但似乎 project_id -field 值被忽略,并导致每当添加新行时将删除以前的数据(具有相同的 user_id 和 resource_id)不同的项目 ID。
所以我的问题是:
是否可以将第三个 id 字段添加到 belongsToMany-association 的槽表中,以便额外的字段也将被视为 id 字段,以便框架知道何时更新或插入记录到连接表?
这个想法是表中的所有三个字段都是唯一的。现在看来,框架丢弃了额外的字段,因此插入和更新无法按预期工作。或者数据库结构中是否存在需要修复的设计缺陷?
我宁愿坚持使用 CakePHP 约定,但似乎这种情况很难解决。任何指导表示赞赏!