【问题标题】:Updating belongsToMany association data更新 belongsToMany 关联数据
【发布时间】:2017-08-18 07:36:34
【问题描述】:

我正在设置一个更新person 和关联的person_to_role 表的表单,person_to_role 是一个中间表,它将person 链接到role 在 n..n 关系中。 role 有一个预定义的角色列表,不应在个人范围内进行修改。

我只需要更新person_to_role表中的role_iddescription并添加/删除记录

SQL

--person
+-------------+-------------+------+-----+---------+----------------+
| Field       | Type        | Null | Key | Default | Extra          |
+-------------+-------------+------+-----+---------+----------------+
| ID          | int(11)     | NO   | PRI | NULL    | auto_increment |
| NICK_NAME   | varchar(16) | YES  |     | NULL    |                |
| FIRST_NAME  | varchar(24) | NO   |     | NULL    |                |
| MIDDLE_NAME | varchar(8)  | YES  |     | NULL    |                |
| LAST_NAME   | varchar(24) | NO   |     | NULL    |                |
| BIRTH_DATE  | date        | NO   |     | NULL    |                |
| GENDER      | varchar(8)  | NO   |     | NULL    |                |
+-------------+-------------+------+-----+---------+----------------+

-- role
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| ID          | int(11)      | NO   | PRI | NULL    | auto_increment |
| NAME        | varchar(24)  | NO   |     | NULL    |                |
| DESCRIPTION | varchar(100) | YES  |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+

--person_to_role
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| ID          | int(11)      | NO   | PRI | NULL    | auto_increment |
| PERSON_ID   | int(11)      | NO   | MUL | NULL    |                |
| ROLE_ID     | int(11)      | NO   | MUL | NULL    |                |
| DESCRIPTION | varchar(100) | YES  |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+

PersonTable 模型

公共函数初始化(数组 $config) { 父::初始化($config);

    $this->setTable('person');
    $this->setDisplayField('ID');
    $this->setPrimaryKey('ID');

    // define relations
    $this->belongsToMany('Role', [
        'joinTable'=> 'person_to_role',
        'foreignKey' => 'PERSON_ID'
    ]);        
}

人控制器 -> 编辑()

public function edit($id = null)
{
    $person = $this->Person->get($id, [
        'contain' => ['role']
    ]);

    $this->set('roles', $this->Person->Role->find('list'));

    if ($this->request->is(['patch', 'post', 'put'])) {            
        $person = $this->Person->patchEntity($person, $this->request->getData());
        if ($this->Person->save($person)) {
            $this->Flash->success(__('The person has been saved.'));

            return $this->redirect(['action' => 'index']);
        }
        $errors = print_r($person->errors(),1);
        $this->Flash->error(__('The person could not be saved. Please, try again.<br><pre>'. $errors .'</pre>'),['escape'=> false]);
    }

    $this->set(compact('person'));
    $this->set('_serialize', ['person']);
}

edit.ctp 表单字段

echo $this->Form->control('NICK_NAME');
echo $this->Form->control('FIRST_NAME');
echo $this->Form->control('MIDDLE_NAME');
echo $this->Form->control('LAST_NAME');
echo $this->Form->control('BIRTH_DATE');
echo $this->Form->control('GENDER',['type'=>'select','options'=>[''=> '- 
Please Select -', 'Male'=>'Male','Female'=>'Female']]);

Assigned roles

...
<?php foreach ($person->role as $k=>$role) { ?>
    <tr><td><?php 

   echo $this->Form->input("role.$k._joinData.ID",['type'=>'hidden','value'=>$person->role[$k]['_joinData']['ID']]);

    echo $this->Form->input("role.$k._joinData.ROLE_ID",['value'=>$role-
>ID,'options'=>$roles,'templates'=>['formGroup' =>'{{input}}']]) 

            ?></td><td>
<?php echo $this->Form->input("role.$k._joinData.DESCRIPTION",    ['value'=>$person->role[$k]['_joinData']['DESCRIPTION'],'templates'=>
['formGroup' =>'{{input}}']]);  ?></td></tr>
        <?php } ?>
...

这给了我以下 POST 数据:

'NICK_NAME' => 'Johny',
    'FIRST_NAME' => 'John',
    'MIDDLE_NAME' => 'J.',
    'LAST_NAME' => 'Smith',
    'BIRTH_DATE' => '1961-01-01',
    'GENDER' => 'Male',
    'role' => [
        (int) 0 => [
            '_joinData' => [
                'ID' => '1',
                'ROLE_ID' => '5',
                'DESCRIPTION' => 'person role description'
            ]
        ]
    ]
]

但更新失败并出现以下错误:

此人无法获救。请再试一次。

  Array
  (
  [role] => Array
  (
    [0] => Array
    (
      [NAME] => Array
      (
        [_required] => This field is required
      )

      [_joinData] => Array
      (
        [PERSON_ID] => Array
        (
          [_required] => This field is required
        )
      )
    )
  )
)

它要求提供person_to_role.person_id,它是foreignKey(它应该知道当前的人ID),并且想要role.name 的值。 我是否设置了我的关联错误?任何帮助表示赞赏。

2017 年 8 月 20 日更新

还是不行,尝试了文档和其他 Internet 资源中所有可能的变体。目前我能够通过验证到 save 操作,但是生成了 INSERT 查询而不是 UPDATE 并且在违反唯一约束时出错。

我有 person.IDperson_to_role.ID 可访问:

protected $_accessible = [
    '*' => true,
    'ID' => true
];

我的 POST 数据如下所示:

[
  'NICK_NAME' => '',
  'FIRST_NAME' => 'test',
  'MIDDLE_NAME' => '',
  'LAST_NAME' => 'user',
  'BIRTH_DATE' => '1996-10-01',
  'GENDER' => 'Male',
  'role' => [
    (int) 0 => [
      '_joinData' => [
        'ID' => '153',
        'DESCRIPTION' => 'test edited text'
      ],
      'ID' => '2'
    ]
  ]
]

我在_joinData 中使用和不使用person_to_role 记录ID 都试过了,结果相同:

INSERT INTO person_to_role (PERSON_ID, ROLE_ID, DESCRIPTION) 
VALUES (129, 2, 'test edited text')

【问题讨论】:

  • 标准 CakePHP belongsToMany 期望您的连接表只包含相关记录的 id。如果您想在此表中存储其他数据,我认为您可能有兴趣使用“通过”选项:book.cakephp.org/3.0/en/orm/…
  • @Szymon 我刚刚尝试按照book.cakephp.org/3.0/en/orm/… 的指示使用“通过”模型,但实体属性role 为空,所以我恢复到上面问题中显示的内容。

标签: cakephp cakephp-3.x


【解决方案1】:

在尝试不同的方法(包括使用'through' association)时,我在PersonToRoleTable.phpmodel 中添加了以下几行:

$this->belongsTo('Person');
$this->belongsTo('Role');

将这些注释掉后,一切都按预期工作,我能够保存更新以及在连接表中添加新记录和删除现有记录。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-15
    • 1970-01-01
    • 2019-09-16
    • 1970-01-01
    • 2022-01-16
    • 2017-02-16
    • 2018-11-28
    • 1970-01-01
    相关资源
    最近更新 更多