使用 CakePHP 3.x 中的控制选项将数据保存到连接 table
Saving data to the join table using control options in CakePHP 3.x
我学会了 如何在 CakePHP 3.x 中添加或编辑 student
时将数据保存到连接 table CoursesMemberships
的字段.为了为许多 courses
添加 grades
我可以在我的 add
和 edit
表格中这样做:
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');
...
但是这个表格:
- 每个
student
有固定数量的courses
;
- 需要 select 列表中的
course id
('type' => 'select'
);
- 将所有课程添加到学生记录中,即使没有参加(好吧,相应的
grade
字段可以保留为空,但仍然如此)。
有没有一种更简单的表格,其中列出了所有 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,显示 grades
表示前 3、5 和 7 courses
,表格强制我选中这三个框。我知道第一条记录消失了,因为我的 courses
以 id=1
开头(等等$key 在循环中)并且因此缺少 'courses.0.id',但一般问题是 beforeMarshal
函数删除的空字段不再以 edit.ctp
形式识别,我找不到编辑 student's
记录的合理方法。
没有构建支持您要实现的目标,您必须想出一个自定义解决方案,这可能需要混合形式和编组逻辑,或者 JavaScript .
例如,您可以创建一个复选框列表,并使用 id
值(如果复选框未选中,则为零,如果 选中,则为 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
选项),否则将为未选中的复选框发送零。
这是一个快速的、未经测试的 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'));
});
});
另见
- Cookbook > Database Access & ORM > Saving Data > Modifying Request Data Before Building Entities
- Cookbook > Views > Helpers > Form > Creating Select, Checkbox and Radio Controls > Options for Control
- Cookbook > Views > Helpers > Form > Creating Select, Checkbox and Radio Controls > Creating Checkboxes
我学会了 student
时将数据保存到连接 table CoursesMemberships
的字段.为了为许多 courses
添加 grades
我可以在我的 add
和 edit
表格中这样做:
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');
...
但是这个表格:
- 每个
student
有固定数量的courses
; - 需要 select 列表中的
course id
('type' => 'select'
); - 将所有课程添加到学生记录中,即使没有参加(好吧,相应的
grade
字段可以保留为空,但仍然如此)。
有没有一种更简单的表格,其中列出了所有 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,显示 grades
表示前 3、5 和 7 courses
,表格强制我选中这三个框。我知道第一条记录消失了,因为我的 courses
以 id=1
开头(等等$key 在循环中)并且因此缺少 'courses.0.id',但一般问题是 beforeMarshal
函数删除的空字段不再以 edit.ctp
形式识别,我找不到编辑 student's
记录的合理方法。
没有构建支持您要实现的目标,您必须想出一个自定义解决方案,这可能需要混合形式和编组逻辑,或者 JavaScript .
例如,您可以创建一个复选框列表,并使用 id
值(如果复选框未选中,则为零,如果 选中,则为 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
选项),否则将为未选中的复选框发送零。
这是一个快速的、未经测试的 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'));
});
});
另见
- Cookbook > Database Access & ORM > Saving Data > Modifying Request Data Before Building Entities
- Cookbook > Views > Helpers > Form > Creating Select, Checkbox and Radio Controls > Options for Control
- Cookbook > Views > Helpers > Form > Creating Select, Checkbox and Radio Controls > Creating Checkboxes