私は少し複雑な部分を含む CakePHP 3 プロジェクトに取り組んでいますが、フレームワークの公式ドキュメントでは探している答えが得られないようです。次のことを行う必要があります。
ユーザーは複数のプロジェクトに所属できます。各プロジェクトでは、現在のプロジェクトに属する各ユーザーがアプリケーションのさまざまなセクションにアクセスできます。これは、リソース ID を格納する Resources というテーブルによって処理されます。
つまり、ユーザー A は、プロジェクト A とプロジェクト B で異なる量のリソースにアクセスできます。
次の関連付けをセットアップしました。
- ユーザーは、UsersProjects を介して、複数のプロジェクトに属しています。
- ユーザーは、UsersResources を介して複数のリソースに属しています
users_resources -table には、次のフィールドがあります。
ユーザー ID | resource_id | project_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 の前の行がテーブルから削除されます。望ましい動作は明らかに、古いレコードがテーブルに残ることです。ただし、値が「append」の saveStrategy-option を UsersTable の Resources-association 定義に追加すると、保存が正しく行われることに気付きました (project_id 2 の行は削除されません)。しかし、append-strategy が使用されているときに既存のレコードを保存しようとすると、保存に失敗します (保存結果が false になります)。
したがって、replace-strategy を使用すると、以前のデータが削除され、append-strategy を使用すると、既存の行を更新すると、ケーキの観点からエラーが発生します。ユニークルールが原因で、ルールチェック中にエラーがスローされたと思います。
置換戦略が進むべき道だと思いますが、 project_id フィールドの値が無視され、新しい行が別の行に追加されるたびに以前のデータ (同じ user_id と resource_id を持つ) が削除されるという状況につながるようです。 project_id。
だから私の質問は:
追加のフィールドも id フィールドと見なされるように、3 番目の id フィールドを belongsToMany-association のトラフ テーブルに追加して、フレームワークがレコードをいつ更新または結合テーブルに挿入するかを認識できるようにすることは可能ですか?
テーブル内の 3 つのフィールドはすべて一意であるという考え方です。フレームワークが余分なフィールドを破棄するように見えるため、挿入と更新が期待どおりに機能しません。それとも、データベース構造に修正が必要な設計上の欠陥がありますか?
私は CakePHP の慣例に固執したいと思いますが、このシナリオに取り組むのは非常に難しいようです。任意のガイダンスをいただければ幸いです。