CakePHP 4 多个复选框
CakePHP 4 multiple checkboxes
我想用数组 JournalEntry[strategy][strategies_conditions]
填充复选框组
然后我想选中包含在 JournalEntry[journal_entries_strategy_conditions]
中的复选框
我显示了复选框,但未正确链接到 name
和 id
的正确字段
这是我在 edit.php
中的代码
<?php
echo $this->Form->control('journal_id', ['options' => $journals]);
echo $this->Form->control('ticket_number');
echo $this->Form->control('strategy_id', ['options' => $strategies, 'empty' => true, 'onChange' => 'getComboA(this)']);
debug($journalEntry);
?>
<div id="stategy-condition">
<?php echo $this->Form->control('journal_entries_strategy_conditions.strategies_condition_id',
[
'type' => 'select',
'multiple' => 'checkbox',
'options' => $journalEntry[strategy][strategies_conditions],
'selected' => $journalEntry[journal_entries_strategy_conditions]
]); ?>
</div>
有了这个我得到了这个输出,你可以看到它使用 object
作为 <label>
并且 <input value="1"
设置为 id
值
<div class="input select">
<label for="strategy-id">Strategy</label>
<input type="hidden" name="strategy_id" value="">
<div class="checkbox">
<label for="strategy-id-0">
<input type="checkbox" name="strategy_id[]" value="0" id="strategy-id-0">{
"id": 1,
"strategy_id": 5,
"name": "zxcasd",
"level": "0",
"created": "2020-08-01T21:21:11+00:00",
"modified": "2020-08-01T21:21:11+00:00"
}</label>
</div>
<div class="checkbox">
<label for="strategy-id-1">
<input type="checkbox" name="strategy_id[]" value="1" id="strategy-id-1">{
"id": 2,
"strategy_id": 5,
"name": "zxcasd",
"level": "0",
"created": "2020-08-01T21:21:11+00:00",
"modified": "2020-08-01T21:21:11+00:00"
}</label>
</div>
<div class="checkbox">
<label for="strategy-id-2">
<input type="checkbox" name="strategy_id[]" value="2" id="strategy-id-2">{
"id": 3,
"strategy_id": 5,
"name": "zxcad",
"level": "0",
"created": "2020-08-01T21:21:11+00:00",
"modified": "2020-08-01T21:21:11+00:00"
}</label></div></div>
这是数据:
object(App\Model\Entity\JournalEntry) {
'id' => (int) 20,
'journal_id' => (int) 1,
'ticket_number' => 'sdfsdfsdf',
'strategy_id' => (int) 5,
'timeframe' => '',
'created' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-25 20:51:42.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'modified' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-25 20:51:42.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'journal_entries_strategy_conditions' => [
(int) 0 => object(App\Model\Entity\JournalEntriesStrategyCondition) {
'id' => (int) 8,
'journal_entry_id' => (int) 20,
'strategies_condition_id' => (int) 1,
'created' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-25 20:51:42.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'modified' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-25 20:51:42.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
}
],
'strategy' => object(App\Model\Entity\Strategy) {
'id' => (int) 5,
'user_id' => (int) 1,
'name' => 'zxcasd',
'description' => 'zxcasd',
'one_hundred_trades' => (int) 0,
'created' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-01 21:21:11.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'modified' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-01 21:21:11.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'strategies_conditions' => [
(int) 0 => object(App\Model\Entity\StrategiesCondition) {
'id' => (int) 1,
'strategy_id' => (int) 5,
'name' => 'zxcasd',
'level' => '0',
'created' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-01 21:21:11.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'modified' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-01 21:21:11.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'[new]' => false,
'[accessible]' => [
'strategy_id' => true,
'name' => true,
'level' => true,
'created' => true,
'modified' => true,
'strategy' => true
]
},
(int) 1 => object(App\Model\Entity\StrategiesCondition) {
'id' => (int) 2,
'strategy_id' => (int) 5,
'name' => 'zxcasd',
'level' => '0',
'created' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-01 21:21:11.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'modified' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-01 21:21:11.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
}
},
(int) 2 => object(App\Model\Entity\StrategiesCondition) {
'id' => (int) 3,
'strategy_id' => (int) 5,
'name' => 'zxcad',
'level' => '0',
'created' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-01 21:21:11.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'modified' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-01 21:21:11.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
}
],
},
'[new]' => false,
这是 edit.php
的请求日期
[
'journal_id' => '1',
'ticket_number' => 'test con',
'pair' => '',
'buy_sell' => '',
'personal_notes' => '',
'entry_date_time' => '',
'entry_price' => '',
'strategy_id' => '5',
'journal_entries_strategy_conditions' => [
'strategies_condition_id' => [
(int) 0 => '1'
]
],
'timeframe' => '',
'position_size' => '',
'sl' => '',
'tp' => '',
'market_conditions' => '',
'entry_toughts' => '',
'close_date_time' => '',
'close_price' => '',
'profit' => '',
'fees' => '',
'high_price' => '',
'low_price' => '',
'exit_thoughts' => '',
'feeling_before' => '',
'feeling_after' => ''
]
add.php
[
'journal_id' => '1',
'ticket_number' => 'sdfdsf',
'pair' => '',
'buy_sell' => '',
'personal_notes' => '',
'entry_date_time' => '',
'entry_price' => '',
'strategy_id' => '5',
'journal_entries_strategy_conditions' => [
(int) 0 => [
'strategies_condition_id' => '1'
],
(int) 1 => [
'strategies_condition_id' => '2'
]
],
'timeframe' => '',
'position_size' => '',
'sl' => '',
'tp' => '',
'market_conditions' => '',
'entry_toughts' => '',
'close_date_time' => '',
'close_price' => '',
'profit' => '',
'fees' => '',
'high_price' => '',
'low_price' => '',
'exit_thoughts' => '',
'feeling_before' => '',
'feeling_after' => ''
]
没有selected
选项,为selection提供值的选项命名为val
或value
,和options
选项一样,它需要一个平面 key => value
数组(如果你想为 <option>
元素提供属性则有一个例外,在这种情况下你可以使用带有 text
和 value
键的嵌套数组).
对于 options
,数组键将用于 <option>
元素的 value
属性,数组值将用于元素的内容。
对于 value
数组值将用于匹配 options
数组的键,即 AFAICT 你需要一个 strategies_condition_id
.
的数组
通常,select 控件的值是使用 list
查找器准备的,您会在烘焙控制器中看到这些值。但是,由于您有嵌套关联,这不一定可行,而且您最好在事后转换数据,这可以使用集合轻松完成。
例如在您的视图模板中:
<div id="stategy-condition">
<?php echo $this->Form->control('journal_entries_strategy_conditions', [
'type' => 'select',
'multiple' => 'checkbox',
'options' =>
collection($journalEntry['strategy']['strategies_conditions'])
->combine('id', 'name')
->toArray(),
'value' =>
collection($journalEntry['journal_entries_strategy_conditions'])
->extract('strategies_condition_id')
->toArray()
]); ?>
</div>
combine()
调用应该构建一个像这样的集合:
[
1 => 'zxcasd',
2 => 'zxcasd',
3 => 'zxcad',
]
和 extract()
应该会产生一个包含以下内容的集合:
[
0 => 1
]
这应该会导致选中第一个复选框。
就您的控件名称问题而言,有很多方法可以解决这个问题,例如,您可以使用自定义模板,在其中对输入名称进行硬编码:
echo $this->Form->control('journal_entries_strategy_conditions', [
'type' => 'select',
// ...
'templates' => [
'checkbox' =>
'<input
type="checkbox"
name="journal_entries_strategy_conditions[][strategies_condition_id]"
value="{{value}}"
{{attrs}}>',
]
]);
- Cookbook > Views > Helpers > Form > Options for Control
- Cookbook > Views > Helpers > Form > Customizing the Templates FormHelper Uses
或者在编组(修补)之前转换数据,使用 JournalEntriesTable
class:
中的 beforeMarshal
回调
public function beforeMarshal(
\Cake\Event\EventInterface $event,
\ArrayObject $data,
\ArrayObject $options
) {
if (isset($data['journal_entries_strategy_conditions']['strategies_condition_id']) {
$ids = $data['journal_entries_strategy_conditions']['strategies_condition_id'];
$conditions = [];
foreach ($ids as $id) {
$conditions[] = [
'strategies_condition_id' => $id,
];
}
$data['journal_entries_strategy_conditions'] = $conditions;
}
}
这将从以下位置转换数据:
'journal_entries_strategy_conditions' => [
'strategies_condition_id' => [
'1',
'2'
],
],
至:
'journal_entries_strategy_conditions' => [
[
'strategies_condition_id' => '1'
],
[
'strategies_condition_id' => '2'
]
],
甚至手动创建单独的复选框,您可以在其中适当地控制每个表单控件的各个方面,包括名称:
echo $this->Form->label('journal_entries_strategy_conditions');
echo $this->Form->hidden('journal_entries_strategy_conditions', ['value' => '']);
$selectedIds = collection($journalEntry['journal_entries_strategy_conditions'])
->extract('strategies_condition_id')
->toArray();
foreach ($journalEntry['strategy']['strategies_conditions'] as $index => $condition) {
echo $this->Form->control(
"journal_entries_strategy_conditions.{$index}.strategies_condition_id",
[
'type' => 'checkbox',
'hiddenField' => false,
'label' => $condition['name'],
'value' => $condition['id'],
'checked' => in_array($condition['id'], $selectedIds, true),
]
);
}
这将创建如下名称属性:
journal_entries_strategy_conditions[0][strategies_condition_id]
journal_entries_strategy_conditions[1][strategies_condition_id]
...
我想用数组 JournalEntry[strategy][strategies_conditions]
填充复选框组然后我想选中包含在 JournalEntry[journal_entries_strategy_conditions]
中的复选框我显示了复选框,但未正确链接到 name
和 id
这是我在 edit.php
中的代码<?php
echo $this->Form->control('journal_id', ['options' => $journals]);
echo $this->Form->control('ticket_number');
echo $this->Form->control('strategy_id', ['options' => $strategies, 'empty' => true, 'onChange' => 'getComboA(this)']);
debug($journalEntry);
?>
<div id="stategy-condition">
<?php echo $this->Form->control('journal_entries_strategy_conditions.strategies_condition_id',
[
'type' => 'select',
'multiple' => 'checkbox',
'options' => $journalEntry[strategy][strategies_conditions],
'selected' => $journalEntry[journal_entries_strategy_conditions]
]); ?>
</div>
有了这个我得到了这个输出,你可以看到它使用 object
作为 <label>
并且 <input value="1"
设置为 id
值
<div class="input select">
<label for="strategy-id">Strategy</label>
<input type="hidden" name="strategy_id" value="">
<div class="checkbox">
<label for="strategy-id-0">
<input type="checkbox" name="strategy_id[]" value="0" id="strategy-id-0">{
"id": 1,
"strategy_id": 5,
"name": "zxcasd",
"level": "0",
"created": "2020-08-01T21:21:11+00:00",
"modified": "2020-08-01T21:21:11+00:00"
}</label>
</div>
<div class="checkbox">
<label for="strategy-id-1">
<input type="checkbox" name="strategy_id[]" value="1" id="strategy-id-1">{
"id": 2,
"strategy_id": 5,
"name": "zxcasd",
"level": "0",
"created": "2020-08-01T21:21:11+00:00",
"modified": "2020-08-01T21:21:11+00:00"
}</label>
</div>
<div class="checkbox">
<label for="strategy-id-2">
<input type="checkbox" name="strategy_id[]" value="2" id="strategy-id-2">{
"id": 3,
"strategy_id": 5,
"name": "zxcad",
"level": "0",
"created": "2020-08-01T21:21:11+00:00",
"modified": "2020-08-01T21:21:11+00:00"
}</label></div></div>
这是数据:
object(App\Model\Entity\JournalEntry) {
'id' => (int) 20,
'journal_id' => (int) 1,
'ticket_number' => 'sdfsdfsdf',
'strategy_id' => (int) 5,
'timeframe' => '',
'created' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-25 20:51:42.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'modified' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-25 20:51:42.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'journal_entries_strategy_conditions' => [
(int) 0 => object(App\Model\Entity\JournalEntriesStrategyCondition) {
'id' => (int) 8,
'journal_entry_id' => (int) 20,
'strategies_condition_id' => (int) 1,
'created' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-25 20:51:42.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'modified' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-25 20:51:42.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
}
],
'strategy' => object(App\Model\Entity\Strategy) {
'id' => (int) 5,
'user_id' => (int) 1,
'name' => 'zxcasd',
'description' => 'zxcasd',
'one_hundred_trades' => (int) 0,
'created' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-01 21:21:11.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'modified' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-01 21:21:11.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'strategies_conditions' => [
(int) 0 => object(App\Model\Entity\StrategiesCondition) {
'id' => (int) 1,
'strategy_id' => (int) 5,
'name' => 'zxcasd',
'level' => '0',
'created' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-01 21:21:11.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'modified' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-01 21:21:11.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'[new]' => false,
'[accessible]' => [
'strategy_id' => true,
'name' => true,
'level' => true,
'created' => true,
'modified' => true,
'strategy' => true
]
},
(int) 1 => object(App\Model\Entity\StrategiesCondition) {
'id' => (int) 2,
'strategy_id' => (int) 5,
'name' => 'zxcasd',
'level' => '0',
'created' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-01 21:21:11.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'modified' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-01 21:21:11.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
}
},
(int) 2 => object(App\Model\Entity\StrategiesCondition) {
'id' => (int) 3,
'strategy_id' => (int) 5,
'name' => 'zxcad',
'level' => '0',
'created' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-01 21:21:11.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'modified' => object(Cake\I18n\FrozenTime) {
'time' => '2020-08-01 21:21:11.000000+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
}
],
},
'[new]' => false,
这是 edit.php
的请求日期[
'journal_id' => '1',
'ticket_number' => 'test con',
'pair' => '',
'buy_sell' => '',
'personal_notes' => '',
'entry_date_time' => '',
'entry_price' => '',
'strategy_id' => '5',
'journal_entries_strategy_conditions' => [
'strategies_condition_id' => [
(int) 0 => '1'
]
],
'timeframe' => '',
'position_size' => '',
'sl' => '',
'tp' => '',
'market_conditions' => '',
'entry_toughts' => '',
'close_date_time' => '',
'close_price' => '',
'profit' => '',
'fees' => '',
'high_price' => '',
'low_price' => '',
'exit_thoughts' => '',
'feeling_before' => '',
'feeling_after' => ''
]
add.php
[
'journal_id' => '1',
'ticket_number' => 'sdfdsf',
'pair' => '',
'buy_sell' => '',
'personal_notes' => '',
'entry_date_time' => '',
'entry_price' => '',
'strategy_id' => '5',
'journal_entries_strategy_conditions' => [
(int) 0 => [
'strategies_condition_id' => '1'
],
(int) 1 => [
'strategies_condition_id' => '2'
]
],
'timeframe' => '',
'position_size' => '',
'sl' => '',
'tp' => '',
'market_conditions' => '',
'entry_toughts' => '',
'close_date_time' => '',
'close_price' => '',
'profit' => '',
'fees' => '',
'high_price' => '',
'low_price' => '',
'exit_thoughts' => '',
'feeling_before' => '',
'feeling_after' => ''
]
没有selected
选项,为selection提供值的选项命名为val
或value
,和options
选项一样,它需要一个平面 key => value
数组(如果你想为 <option>
元素提供属性则有一个例外,在这种情况下你可以使用带有 text
和 value
键的嵌套数组).
对于 options
,数组键将用于 <option>
元素的 value
属性,数组值将用于元素的内容。
对于 value
数组值将用于匹配 options
数组的键,即 AFAICT 你需要一个 strategies_condition_id
.
通常,select 控件的值是使用 list
查找器准备的,您会在烘焙控制器中看到这些值。但是,由于您有嵌套关联,这不一定可行,而且您最好在事后转换数据,这可以使用集合轻松完成。
例如在您的视图模板中:
<div id="stategy-condition">
<?php echo $this->Form->control('journal_entries_strategy_conditions', [
'type' => 'select',
'multiple' => 'checkbox',
'options' =>
collection($journalEntry['strategy']['strategies_conditions'])
->combine('id', 'name')
->toArray(),
'value' =>
collection($journalEntry['journal_entries_strategy_conditions'])
->extract('strategies_condition_id')
->toArray()
]); ?>
</div>
combine()
调用应该构建一个像这样的集合:
[
1 => 'zxcasd',
2 => 'zxcasd',
3 => 'zxcad',
]
和 extract()
应该会产生一个包含以下内容的集合:
[
0 => 1
]
这应该会导致选中第一个复选框。
就您的控件名称问题而言,有很多方法可以解决这个问题,例如,您可以使用自定义模板,在其中对输入名称进行硬编码:
echo $this->Form->control('journal_entries_strategy_conditions', [
'type' => 'select',
// ...
'templates' => [
'checkbox' =>
'<input
type="checkbox"
name="journal_entries_strategy_conditions[][strategies_condition_id]"
value="{{value}}"
{{attrs}}>',
]
]);
- Cookbook > Views > Helpers > Form > Options for Control
- Cookbook > Views > Helpers > Form > Customizing the Templates FormHelper Uses
或者在编组(修补)之前转换数据,使用 JournalEntriesTable
class:
beforeMarshal
回调
public function beforeMarshal(
\Cake\Event\EventInterface $event,
\ArrayObject $data,
\ArrayObject $options
) {
if (isset($data['journal_entries_strategy_conditions']['strategies_condition_id']) {
$ids = $data['journal_entries_strategy_conditions']['strategies_condition_id'];
$conditions = [];
foreach ($ids as $id) {
$conditions[] = [
'strategies_condition_id' => $id,
];
}
$data['journal_entries_strategy_conditions'] = $conditions;
}
}
这将从以下位置转换数据:
'journal_entries_strategy_conditions' => [
'strategies_condition_id' => [
'1',
'2'
],
],
至:
'journal_entries_strategy_conditions' => [
[
'strategies_condition_id' => '1'
],
[
'strategies_condition_id' => '2'
]
],
甚至手动创建单独的复选框,您可以在其中适当地控制每个表单控件的各个方面,包括名称:
echo $this->Form->label('journal_entries_strategy_conditions');
echo $this->Form->hidden('journal_entries_strategy_conditions', ['value' => '']);
$selectedIds = collection($journalEntry['journal_entries_strategy_conditions'])
->extract('strategies_condition_id')
->toArray();
foreach ($journalEntry['strategy']['strategies_conditions'] as $index => $condition) {
echo $this->Form->control(
"journal_entries_strategy_conditions.{$index}.strategies_condition_id",
[
'type' => 'checkbox',
'hiddenField' => false,
'label' => $condition['name'],
'value' => $condition['id'],
'checked' => in_array($condition['id'], $selectedIds, true),
]
);
}
这将创建如下名称属性:
journal_entries_strategy_conditions[0][strategies_condition_id]
journal_entries_strategy_conditions[1][strategies_condition_id]
...