Yii2:如何将属性中的CSV字符串映射到表单中的CheckboxList?

问题描述 投票:0回答:4

我有一个模型,其属性包含 CSV 字符串。

(该模型实际上是一个 ActiveRecord 对象,但我想这并不重要。如果我错了,请纠正我。)

/**
 * @property string $colors Can be something like "red" or "red,green,blue" or ""
 */
class Product extends Model {        
}

我有一个表单,我想在其中将此属性显示为 checkboxList ,以便用户可以通过简单的单击来选择可能的值,而不是在文本输入中键入。

理论上,它应该类似于这样:

<?php $availableColors = ['red' => 'Red', 'green' => 'Green', 'blue' => 'Blue']; ?>

<?php $form = ActiveForm::begin([]); ?>
    <?= $form->field($model, 'colors')->checkboxList($availableColors) ?>
<?php ActiveForm::end(); ?>

这显然不起作用,因为字段

colors
需要是一个数组。但在我的模型中它是一个字符串。

实现这一目标的好方法是什么?用JS还是伪属性?

colors
属性不得更改,因为它已在其他不应修改的上下文中使用。

php csv activerecord model yii2
4个回答
1
投票

您可以重写模型中的

beforeValidate
方法,将
implode
颜色数组转换为字符串。在您看来,您可以使用以下内容:

<?= $form->field($model, 'colors')->checkboxList($availableColors, 
       [
            'item'=> function ($index, $label, $name, $checked, $value) use ($model) {
                $colors = explode(';', $model->colors);
                $checked = in_array($value, $colors);
                return Html::checkbox($name, $checked, [
                    'value' => $value,
                    'label' => $label,
                ]);
             }
       ]) ?>

0
投票

CSV 是一种文件格式,用于在本机以不兼容格式运行的程序之间移动表格数据。使用它作为模型属性并不是很优雅(说得好听一点)。在我看来,您应该开始将颜色存储在数组中。

话虽这么说,您可以使用模型中的

beforeValidate()
函数将下拉列表中的数组数据转换为 CSV:

public function beforeValidate() {
    $this->colors = explode(';', $this->colors);

    return parent::beforeValidate();
}

0
投票

我认为这是一个 PHP 问题,但无论如何你可以使用 PHP Explode 来构建你需要的数组。请参阅 here 了解更多详细信息,然后使用 checkboxList 中的数组


0
投票

现在我用表单的额外模型解决了这个问题。在我看来,这是一个正确的解决方案。

/**
 * @property string $colors Can be something like "red" or "red,green,blue" or ""
 */
class Product extends Model {
}

/**
 * @property string[] $colorsAsArray
 */
class ProductForm extends Product {

    public function rules() {
        return array_merge(parent::rules(), [
            ['colorsAsArray', 'safe'] // just to make it possible to use load()
        ]);
    }

    public function getColorsAsArray() {
        return explode(',', $this->colors);
    }

    public function setColorsAsArray($value) {
        $this->colors = self::implode($value);
    }

    protected static function implode($value) {
        if ($value == 'none-value') return '';
        return implode(',', $value);
    }

    /* - - - - - - - - - - optional - - - - - - - - - - */

    public function attributeLabels() {
        $attributeLabels = parent::attributeLabels();
        return array_merge($attributeLabels, [
            'colorsAsArray' => $attributeLabels['colors'],
        ]);
    }
}

这样我就可以这样使用表格了:

<?php $availableColors = ['red' => 'Red', 'green' => 'Green', 'blue' => 'Blue']; ?>

<?php $form = ActiveForm::begin([]); ?>
    <?= $form->field($model, 'colorsAsArray')
             ->checkboxList($availableColors, ['unselect' => 'none-value']) ?>
<?php ActiveForm::end(); ?>

当然,现在控制器必须使用继承的模型类。

如果未选中任何复选框,该解决方案也可以解决该问题。这就是引入

'none-value'
的原因。

© www.soinside.com 2019 - 2024. All rights reserved.