复选框 HTML 数组语法在 CakePHP 4 中不起作用
Checkbox HTML array syntax doesn't work in CakePHP 4
我在 CakePHP 4 中有一个应用程序,我正在做与 Make array from checkbox form
中描述的等效的事情
我的标记很简单:
<input type="checkbox" name="services[]" value="Service 1" id="service1">
<input type="checkbox" name="services[]" value="Service 2" id="service2">
<input type="checkbox" name="services[]" value="Service 3" id="service3">
所以有人可以例如检查“服务 1”和“服务 3”并省略“服务 2”,例如
我使用 CakePHP 中的表单助手来生成上面的 HTML。代码看起来像这样,并且在该页面的模板文件中:
<?= $this->Form->checkbox('services[]', ['value' => 'Service 1', 'id' => 'service1', 'hiddenField' => false]); ?>
<?= $this->Form->checkbox('services[]', ['value' => 'Service 2', 'id' => 'service2', 'hiddenField' => false]); ?>
<?= $this->Form->checkbox('services[]', ['value' => 'Service 3', 'id' => 'service3', 'hiddenField' => false]); ?>
当我提交表单并调试输出时:
// in my Controller
if ($this->request->is('post')) {
debug($this->request->getData());
}
我得到:
'services' => [
(int) 0 => 'Service 1',
(int) 1 => 'Service 3',
],
这很好,因为它有选定的服务,就用户在表单的这一部分提交的数据而言,这是我所需要的。
但是当提交表单后提交错误时:
Notice (8): Array to string conversion [CORE/src/View/Widget/CheckboxWidget.php, line 93]
None 的复选框被选中(而表单上的其余字段填充了请求数据,尽管它们都是文本输入而不是复选框)。看起来像这样:
为什么会这样?正在生成的标记使用复选框名称的数组语法(例如 services[]
),据我所见,它是完全有效的 HTML 并且在链接 post 上使用的东西没有有人说这是个问题。
这是 CakePHP 的特定问题(例如,Form Helper 某处使用了错误的语法)还是 HTML 或 PHP 的解释方式的一般问题?
我记得我曾经为我的项目写过一个帮助程序
类似于
namespace App\View\Helper;
use Cake\View\Helper\FormHelper;
/**
* Allows forms with fieldname[] syntax.
*
* @author Mark Scherer
* @license MIT
* @property \Cake\View\Helper\UrlHelper $Url
* @property \App\View\Helper\HtmlHelper $Html
*/
class ArrayFormHelper extends FormHelper
{
/**
* @var int
*/
protected $counter = 0;
/**
* @var array
*/
protected $data = [];
/**
* @param array $config
*
* @return void
*/
public function initialize(array $config): void
{
$this->data = $this->getView()->getRequest()->getData();
}
/**
* @return void
*/
public function endRow(): void
{
$this->counter++;
}
/**
* @return void
*/
public function reset(): void
{
$this->counter = 0;
}
/**
* @param string $field
* @param array $options
*
* @return string
*/
public function arrayControl(string $field, array $options = []): string
{
if (array_key_exists($this->counter, $this->data[$field])) {
$options['default'] = $this->data[$field][$this->counter];
$this->getView()->setRequest($this->getView()->getRequest()->withoutData($field));
}
return $this->control($field . '[]', $options);
}
}
用作示例
echo $this->ArrayForm->arrayControl('module', ['label' => 'Module', 'placeholder' => 'CamelCase']);
echo $this->ArrayForm->arrayControl('type', ['label' => 'Type', 'options' => ['patch' => 'patch', 'minor' => 'minor', 'major' => 'major'], 'empty' => true]);
$this->ArrayForm->endRow();
如果这不在循环内(就像我的情况一样),则不需要 counter 和 endRow 的东西。
您的字段名称与数据名称相同,例如 services
,因此表单助手将为每个单独控件的当前值选取一个数组,这将失败,因为“ 应该检查”逻辑需要比较两个平面值。
如果你想像这样创建单独的复选框,那么你要么需要注意为单独的控件传递可能的 POST 数据,这就是 mark 的例子所做的,或者你需要测试手动输入数据并标记相应的复选框,这是一个示例:
$values = (array)$this->Form->getSourceValue('services');
echo $this->Form->checkbox('services[]', [
'value' => 'first',
'checked' => in_array('first', $values),
// ...
]);
echo $this->Form->checkbox('services[]', [
'value' => 'second',
'checked' => in_array('second', $values),
'hiddenField' => false,
// ...
]);
echo $this->Form->checkbox('services[]', [
'value' => 'third',
'checked' => in_array('third', $values),
'hiddenField' => false,
// ...
]);
话虽这么说,对于您的特定情况,您应该能够简单地使用多复选框控件,它将处理查找数据并自动标记复选框:
echo $this->Form->select(
'services',
$options,
['multiple' => 'checkbox', /* ... */]
);
如果您想使用名称作为选项值,$options
需要是一个数组,例如:
[
'Service 1' => 'Service 1',
'Service 2' => 'Service 2',
// ...
]
因为数组索引用于复选框值,而数组值用于复选框标签。
另见
我在 CakePHP 4 中有一个应用程序,我正在做与 Make array from checkbox form
中描述的等效的事情我的标记很简单:
<input type="checkbox" name="services[]" value="Service 1" id="service1">
<input type="checkbox" name="services[]" value="Service 2" id="service2">
<input type="checkbox" name="services[]" value="Service 3" id="service3">
所以有人可以例如检查“服务 1”和“服务 3”并省略“服务 2”,例如
我使用 CakePHP 中的表单助手来生成上面的 HTML。代码看起来像这样,并且在该页面的模板文件中:
<?= $this->Form->checkbox('services[]', ['value' => 'Service 1', 'id' => 'service1', 'hiddenField' => false]); ?>
<?= $this->Form->checkbox('services[]', ['value' => 'Service 2', 'id' => 'service2', 'hiddenField' => false]); ?>
<?= $this->Form->checkbox('services[]', ['value' => 'Service 3', 'id' => 'service3', 'hiddenField' => false]); ?>
当我提交表单并调试输出时:
// in my Controller
if ($this->request->is('post')) {
debug($this->request->getData());
}
我得到:
'services' => [
(int) 0 => 'Service 1',
(int) 1 => 'Service 3',
],
这很好,因为它有选定的服务,就用户在表单的这一部分提交的数据而言,这是我所需要的。
但是当提交表单后提交错误时:
Notice (8): Array to string conversion [CORE/src/View/Widget/CheckboxWidget.php, line 93]
None 的复选框被选中(而表单上的其余字段填充了请求数据,尽管它们都是文本输入而不是复选框)。看起来像这样:
为什么会这样?正在生成的标记使用复选框名称的数组语法(例如 services[]
),据我所见,它是完全有效的 HTML 并且在链接 post 上使用的东西没有有人说这是个问题。
这是 CakePHP 的特定问题(例如,Form Helper 某处使用了错误的语法)还是 HTML 或 PHP 的解释方式的一般问题?
我记得我曾经为我的项目写过一个帮助程序 类似于
namespace App\View\Helper;
use Cake\View\Helper\FormHelper;
/**
* Allows forms with fieldname[] syntax.
*
* @author Mark Scherer
* @license MIT
* @property \Cake\View\Helper\UrlHelper $Url
* @property \App\View\Helper\HtmlHelper $Html
*/
class ArrayFormHelper extends FormHelper
{
/**
* @var int
*/
protected $counter = 0;
/**
* @var array
*/
protected $data = [];
/**
* @param array $config
*
* @return void
*/
public function initialize(array $config): void
{
$this->data = $this->getView()->getRequest()->getData();
}
/**
* @return void
*/
public function endRow(): void
{
$this->counter++;
}
/**
* @return void
*/
public function reset(): void
{
$this->counter = 0;
}
/**
* @param string $field
* @param array $options
*
* @return string
*/
public function arrayControl(string $field, array $options = []): string
{
if (array_key_exists($this->counter, $this->data[$field])) {
$options['default'] = $this->data[$field][$this->counter];
$this->getView()->setRequest($this->getView()->getRequest()->withoutData($field));
}
return $this->control($field . '[]', $options);
}
}
用作示例
echo $this->ArrayForm->arrayControl('module', ['label' => 'Module', 'placeholder' => 'CamelCase']);
echo $this->ArrayForm->arrayControl('type', ['label' => 'Type', 'options' => ['patch' => 'patch', 'minor' => 'minor', 'major' => 'major'], 'empty' => true]);
$this->ArrayForm->endRow();
如果这不在循环内(就像我的情况一样),则不需要 counter 和 endRow 的东西。
您的字段名称与数据名称相同,例如 services
,因此表单助手将为每个单独控件的当前值选取一个数组,这将失败,因为“ 应该检查”逻辑需要比较两个平面值。
如果你想像这样创建单独的复选框,那么你要么需要注意为单独的控件传递可能的 POST 数据,这就是 mark 的例子所做的,或者你需要测试手动输入数据并标记相应的复选框,这是一个示例:
$values = (array)$this->Form->getSourceValue('services');
echo $this->Form->checkbox('services[]', [
'value' => 'first',
'checked' => in_array('first', $values),
// ...
]);
echo $this->Form->checkbox('services[]', [
'value' => 'second',
'checked' => in_array('second', $values),
'hiddenField' => false,
// ...
]);
echo $this->Form->checkbox('services[]', [
'value' => 'third',
'checked' => in_array('third', $values),
'hiddenField' => false,
// ...
]);
话虽这么说,对于您的特定情况,您应该能够简单地使用多复选框控件,它将处理查找数据并自动标记复选框:
echo $this->Form->select(
'services',
$options,
['multiple' => 'checkbox', /* ... */]
);
如果您想使用名称作为选项值,$options
需要是一个数组,例如:
[
'Service 1' => 'Service 1',
'Service 2' => 'Service 2',
// ...
]
因为数组索引用于复选框值,而数组值用于复选框标签。
另见