使用CakePHP 3.x中的控件选项将数据保存到连接表

时间:2017-08-29 10:04:45

标签: mysql cakephp cakephp-3.0 jointable

我了解here如何在CakePHP 3.x中添加或编辑CoursesMemberships时将数据保存到连接表student的字段中。要为许多grades添加courses,我可以使用addedit表单执行此操作:

echo $this->Form->control('courses.0.id', ['type' => 'select', 'options' => $courses]);
echo $this->Form->control('courses.0._joinData.grade');

echo $this->Form->control('courses.1.id', ['type' => 'select', 'options' => $courses]);
echo $this->Form->control('courses.1._joinData.grade');

echo $this->Form->control('courses.2.id', ['type' => 'select', 'options' => $courses]);
echo $this->Form->control('courses.2._joinData.grade');
...

但是这个形式:

  1. 每个courses都有固定数量student;
  2. 需要从列表中选择course id'type' => 'select');
  3. 即使没有参加,也会将所有课程添加到学生记录中(相应的grade字段可以保留为空,但仍然是。)
  4. 有没有办法让一个更简单的表单,其中列出了所有courses,只有course参加了一个复选框并输入相应的grade?我发现使用control ...

    非常具有挑战性

    修改@ndm提出了一个非常好的方法之后,我在add.ctp

    中实现了它
    foreach ($courses as $key => $course) {
    
    echo $this->Form->control('courses.'.$key.'.id', ['type' => 'checkbox', 'hiddenField' => false, 'value' => $key,
        'label' => $key]);
    echo $this->Form->control('courses.'.$key.'._joinData.grades');
    }
    

    并相应更正StudentsTable.php。它运行没有问题。

    但是,如果我在edit.ctp中执行相同操作,则之前保存的记录(例如1,3,5和7 courses现在列为1,2和3,显示{{1}对于前第3和第5 grades而且表单强制我检查这三个框。我知道第一条记录消失了,因为我的coursescourses开头(所以因此缺少循环中的$ key和' courses.0.id'但一般的问题是id=1beforeMarshal函数不再识别由edit.ctp函数删除的空字段表格,我找不到合理的方式来编辑student's记录。

1 个答案:

答案 0 :(得分:1)

没有支持你想要实现的目标,你必须提出一个自定义解决方案,这可能需要混合使用表单和编组逻辑,或者JavaScript。

您可以创建一个复选框列表,并使用id值(如果未选中复选框,则为零;如果 选中)在编组之前从提交的数据中删除未经检查的条目,如下所示:

echo $this->Form->control('courses.0.id', [
    'type' => 'checkbox',
    'value' => $courses[0]->id,
    'label' => $courses[0]->title
]);
echo $this->Form->control('courses.0._joinData.grade');

echo $this->Form->control('courses.1.id', [
    'type' => 'checkbox',
    'value' => $courses[1]->id,
    'label' => $courses[1]->title
]);
echo $this->Form->control('courses.1._joinData.grade');

// ...
// in the `StudentsTable` class

public function beforeMarshal(\Cake\Event\Event $event, \ArrayObject $data, \ArrayObject $options)
{
    forach ($data['courses'] as $key => $course) {
        if (empty($course['id'])) {
            unset($data['courses'][$key])
        }
    }
}

或者,您可以使用JavaScript来禁用与复选框相关的控件,这样它们就不会被提交。为了使其正常工作,您需要确保禁用默认情况下为复选框生成的隐藏字段(请参阅hiddenField选项),否则将为未选中的复选框发送零。< / p>

这是一个快速,未经测试的jQuery示例来说明原理:

echo $this->Form->control('courses.0.id', [
    'class' => 'course-checkbox',
    'data-join-data-input' => '#course-join-data-0',
    'type' => 'checkbox',
    'hiddenField' => false, // no fallback, unchecked boxes aren't being submitted
    'value' => $courses[0]->id,
    'label' => $courses[0]->title
]);
echo $this->Form->control('courses.0._joinData.grade', [
    'id' => 'course-join-data-0',
    'disabled' => true
]);

// ...
$('.course-checkbox').each(function () {
    var $checkbox = $(this);
    var $joinDataInput = $($checkbox.data('join-data-input'));

    $checkbox.on('change', function () {
        $joinDataInput.prop('disabled', !$checkbox.prop('checked'));
    });
});

另见