【问题标题】:saving belongsToMany association with same keys but different _joinData使用相同的键但不同的 _joinData 保存 belongsToMany 关联
【发布时间】:2019-10-02 21:44:09
【问题描述】:

我在使用through 表配置的两个表之间有belongsToMany 关系。

class UsersTable extends Table
{
   public function initialize(array $config)
   {
       $this->belongsToMany('Groups', [
           'through' => 'GroupsUsers',
       ]);
   }
}

class GroupsTable extends Table
{
   public function initialize(array $config)
   {
       $this->belongsToMany('Users', [
           'through' => 'GroupsUsers',
       ]);
   }
}

class GroupsUsersTable extends Table
{
   public function initialize(array $config)
   {
       $this->belongsTo('Groups');
       $this->belongsTo('Users');
   }
}

我可以在用户和组之间建立关联,但不是我不知道如何在同一个用户和组之间建立多个关联,但使用不同的_joinData

这是连接表的构建方式:

$table = $this->table('groups_users');

$table->addColumn('user_id', 'integer');
$table->addColumn('group_id', 'integer');
$table->addColumn('role', 'string');

$table->create();

当我通过添加用户来添加或编辑组时,beforeMarshal() 中的$data

object(ArrayObject) {
    name => 'test group'
    users => [
        (int) 0 => [
            'id' => (int) 1,
            '_joinData' => [
                'role' => 'writer'
            ]
        ],
        (int) 1 => [
            'id' => (int) 1,
            '_joinData' => [
                'role' => 'editor'
            ]
        ]
    ]
}

修补控制器中的实体后
$entity = $this->Groups->patchEntity(
    $entity,
    $data,
    ['associated' => ['Users._joinData']]
);

我在beforeSave() 中得到以下$entity

object(App\Model\Entity\Group) {

    'id' => (int) 1,
    'name' => 'test group',
    'users' => [
        (int) 0 => object(App\Model\Entity\User) {

            'id' => (int) 1,
            'username' => 'testuser',
            '_joinData' => object(Cake\ORM\Entity) {

                'role' => 'writer',
                '[new]' => true,
                '[accessible]' => [
                    '*' => true
                ],
                '[dirty]' => [
                    'role' => true
                ],
                '[original]' => [],
                '[virtual]' => [],
                '[hasErrors]' => false,
                '[errors]' => [],
                '[invalid]' => [],
                '[repository]' => 'GroupsUsers'

            },
            '[new]' => false,
            '[accessible]' => [
                'username' => true,
                'groups' => true,
                '_joinData' => true
            ],
            '[dirty]' => [
                '_joinData' => true
            ],
            '[original]' => [
                '_joinData' => [
                    'role' => 'writer'
                ]
            ],
            '[hasErrors]' => false,
            '[errors]' => [],
            '[invalid]' => [],
            '[repository]' => 'Users'

        }
    ],

    '[new]' => false,
    '[accessible]' => [
        'name' => true,
        'users' => true
    ],
    '[dirty]' => [
        'users' => true,
        'modified' => true
    ],
    '[original]' => [
        'modified' => object(Cake\I18n\FrozenTime) {

            'time' => '2019-05-15T14:41:49+00:00',
            'timezone' => 'UTC',
            'fixedNowTime' => false

        }
    ],
    '[hasErrors]' => false,
    '[errors]' => [],
    '[invalid]' => [],
    '[repository]' => 'Groups'

}

所以看起来 Marshaller 正在从组中删除第二个“重复”用户,即使 _joinData 不同。默认saveStrategyreplace,但手动将其更改为append 也不会添加第二个关联。

如何使用同一个连接表将同一个用户添加到具有不同_joinData 的同一个组中。

【问题讨论】:

    标签: cakephp orm associations has-and-belongs-to-many cakephp-3.7


    【解决方案1】:

    marshaller 使用主键来标识记录,现有实体的集合将只保存一个用户实体实例,因此即使 marshaller 将添加不同的连接数据集,它也会将其设置为一个相同的实体......长话短说,编组器(还)没有能力做你想做的事情。如果还没有问题,您可能需要打开一个问题 over at GitHub

    现在您必须单独保存记录,例如像这样(未经测试,但您明白了):

    $group = $this->Groups->patchEntity($entity, $data, [
        'fieldList' => ['name']
    ]);
    
    $users = [];
    foreach ($data['users'] as $userData) {
        $user = $this->Groups->Users->newEntity();
        $users[] = $this->Groups->Users->patchEntity($user, $userData);
    }
    
    $result = $this->Groups->getConnection()->transactional(function () use ($group, $users) {
        if (!$this->Groups->save($group, ['atomic' => false])) {
            return false;
        }
    
        if (!$this->Groups->Users->link($group, $users, ['atomic' => false])) {
            return false;
        }
    
        return true;
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多