Cakephp 3 - belongsToMany关联通过表中的附加ID字段

时间:2016-02-05 08:26:01

标签: cakephp orm cakephp-3.x

我一直在开发一个CakePHP 3项目,其上有一些部分更复杂,似乎框架的官方文档没有给我我想要的答案。需要做以下事情:

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

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

我设置了以下关联:

  1. 用户通过UsersProjects属于多个项目
  2. 用户通过UsersResources属于多个资源
  3. 在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惯例,但似乎这种情况很难解决。任何指导表示赞赏!

0 个答案:

没有答案