сохранение принадлежит одной ассоциации с одинаковыми ключами, но разными _joinData - PullRequest
0 голосов
/ 15 мая 2019

У меня есть отношение belongsToMany между двумя таблицами, которое настроено с использованием таблицы through.

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();

Когда я добавляю или редактирую группу, добавляя в нее пользователей, $data в beforeMarshal() равно

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']]
);

Я получаю следующее $entity в beforeSave()

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'

}

Похоже, маршаллер удаляет второго «дубликата» пользователя из группы, хотя _joinData отличается. По умолчанию saveStrategy равно replace, но изменение вручную на append также не добавляет вторую связь.

Как добавить одного и того же пользователя в одну группу с разными _joinData, используя одну и ту же таблицу соединений.

1 Ответ

1 голос
/ 16 мая 2019

Маршаллер использует первичный ключ для идентификации записей, и коллекция существующих сущностей будет содержать только один экземпляр сущности пользователя, поэтому, даже если маршаллер добавит разные наборы данных соединения, он установит его на один и тот же сущность ... Короче говоря, маршаллер (пока) не способен делать то, что вы пытаетесь сделать. Возможно, вы захотите открыть проблему на 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;
});
...