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

时间:2015-04-21 09:19:39

标签: csv activerecord model attributes yii2

我的模型的属性包含CSV字符串。

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

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

我有一个表单,我希望将此属性显示为checkboxList,以便用户可以通过简单的点击选择可能的值,而不是键入textInput。

理论上,它应该与此类似:

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

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

这显然不起作用,因为字段colors需要是一个数组。但在我的模型中它是一个字符串。

实现这一目标的好方法是什么?使用JS还是伪属性? colors属性不得更改,因为它已在其他不应修改的上下文中使用。

4 个答案:

答案 0 :(得分:1)

您可以在模型中覆盖beforeValidate方法,将{color 1}颜色数组覆盖为字符串。在您的视图中,您可以使用以下内容:

implode

答案 1 :(得分:0)

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

中使用该数组

答案 2 :(得分:0)

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

话虽如此,您可以使用模型中的beforeValidate()函数将数组数据从下拉列表转换为CSV:

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

    return parent::beforeValidate();
}

答案 3 :(得分: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'被引入的原因。