0

私は少し複雑な部分を含む CakePHP 3 プロジェクトに取り組んでいますが、フレームワークの公式ドキュメントでは探している答えが得られないようです。次のことを行う必要があります。

ユーザーは複数のプロジェクトに所属できます。各プロジェクトでは、現在のプロジェクトに属する各ユーザーがアプリケーションのさまざまなセクションにアクセスできます。これは、リソース ID を格納する Resources というテーブルによって処理されます。

つまり、ユーザー A は、プロジェクト A とプロジェクト B で異なる量のリソースにアクセスできます。

次の関連付けをセットアップしました。

  1. ユーザーは、UsersProjects を介して、複数のプロジェクトに属しています。
  2. ユーザーは、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_idresource_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 の慣例に固執したいと思いますが、このシナリオに取り組むのは非常に難しいようです。任意のガイダンスをいただければ幸いです。

4

0 に答える 0