我一直在开发一个CakePHP 3项目,其上有一些部分更复杂,似乎框架的官方文档没有给我我想要的答案。需要做以下事情:
用户可以属于多个项目。在每个项目中,属于当前项目的每个用户都可以访问应用程序的不同部分,这由一个名为Resources的表处理,该表存储资源ID。
简而言之,用户A可以访问项目A和项目B中的不同数量的资源。
我设置了以下关联:
在users_resources -table中,我有以下字段:
user_id | resource_id | PROJECT_ID
project_id -field被添加到表中以使用户的资源特定于项目。
关联配置如下:
UsersTable:
$this->belongsToMany('Resources', [
'foreignKey' => 'user_id',
'targetForeignKey' => 'resource_id',
'joinTable' => 'users_resources',
'through' => 'UsersResources'
]);
ResourcesTable:
$this->belongsToMany('Users', [
'foreignKey' => 'resource_id',
'targetForeignKey' => 'user_id',
'joinTable' => 'users_resources',
'through' => 'UsersResources'
]);
UsersResourcesTable:
$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的Resources-association定义中添加值为'append'的saveStrategy-option会使保存正常进行(不会删除带有project_id 2的行)。但是当我尝试在使用append-strategy时保存现有记录时,保存将失败(保存结果为false)。
因此,如果我使用replace-strategy,之前的数据会被删除,如果我使用append-strategy,现有行的更新将导致cake的视角出错。我认为由于unique-rule,在规则检查期间会抛出错误。
我认为替换策略是可行的方法,但似乎project_id -field值被忽略,并且导致以下情况:每当添加新行时,将删除先前的数据(具有相同的user_id和resource_id)使用不同的project_id。
所以我的问题是:
是否可以向belongsToMany-association的槽表添加第三个id-field,以便额外的字段也可以被视为id-field,因此框架将知道何时更新或向连接表插入记录?
这个想法是表中的所有三个字段都是唯一的。现在看来框架丢弃了额外的字段,因此插入和更新不能按预期工作。或者数据库结构中是否存在需要修复的设计缺陷?
我更喜欢坚持CakePHP惯例,但似乎这种情况很难解决。任何指导表示赞赏!