首页 > 解决方案 > CakePHP 4 多个复选框

问题描述

我想用数组 JournalEntry[strategy][strategies_conditions] 填充一个复选框组

然后我希望选中包含在 JournalEntry[journal_entries_strategy_conditions] 中的复选框

我有复选框显示但没有正确链接到正确的字段nameid

这是我在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>

有了这个,我得到了这个输出,你可以看到它正在使用objectfor<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' => ''
]

添加.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' => ''
]

标签: cakephpcakephp-4.x

解决方案


没有selected选项,为选择提供值的选项被命名为valor value,和options选项一样,它需要一个平面key => value数组(如果您想为<option>元素提供属性,则有一个例外,在这种情况下,您可以使用嵌套数组textvalue键)。

因为options数组键将用于<option>元素的value属性,数组值将用于元素的内容。

因为value数组值将用于匹配options数组的键,即 AFAICT,您需要一个strategies_condition_id.

通常使用查找器准备选择控件的值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}}>',
    ]
]);

或者在编组(修补)之前转换数据,使用类中的beforeMarshal回调JournalEntriesTable

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]
...

推荐阅读