如何在Yii中为自定义CActiveRecord属性设置验证规则?

时间:2015-07-11 17:39:27

标签: forms yii view model yii-cactiverecord

我正在开发一个带有数据库的Yii项目,该数据库包含一个表,其中几乎所有数据都作为JSON保存在字段中(它很疯狂,但它就是 ):

id      INTEGER
user_id INTEGER
data    LONGTEXT

此“JSON字段”data具有以下结构,并且除其他外包含图像:

{
   "id":"1",
   "foo":"bar",
   ...
   "data":{
      "baz":"buz",
      ...
    }
}

显示它没有问题,但现在我想使数据可编辑。我的表格如下:

<?php
$form = $this->beginWidget('CActiveForm', array(
    'id' => 'my-form',
    'htmlOptions' => array('enctype' => 'multipart/form-data'),
    'enableAjaxValidation'=>false,
));
?>
<div class="row">
    <?php echo $form->labelEx($model, 'foo'); ?>
    <?php
    echo $form->textField($model, 'foo', array(...));
    ?>
    <?php echo $form->error($model, 'foo'); ?>
</div>
<div class="row">
    <?php echo $form->labelEx($model, 'baz'); ?>
    <?php
    echo $form->textField($model, 'data[baz]', array(...));
    ?>
    <?php echo $form->error($model, 'data[baz]'); ?>
</div>

有效。但是有很多问题,似乎是由同一件事引起的 - 他的表单字段没有引用模型属性/属性:

  1. 当我要求字段foobaz需要public function rules() { return array(array('foo, baz', 'required')); } - 属性$foo已定义时)foo bahaves如愿,但baz导致“ foo 不能为空”错误。因此,我无法将data[*]设置为required

  2. 如果表单无效并重新加载,则所有data[*]字段均为空。

  3. data[*]字段未标记为必填字段。

  4. 有没有要解决这个问题而不改变数据结构?没有正确的方法,但也许是一种解决方法。

1 个答案:

答案 0 :(得分:0)

以这种方式验证字段是不可能的。首先,如果您在模型中使用字段,则必须在表中定义或存在活动记录。因此,如果您想验证这种结构是唯一正确的方法:

class Model extends CActiveRecord {
  // Define public varialble
  public $data_baz;

  public function rules(){
    return array(
      // Add it to rules
      array( 'data_baz', 'required' )
    );
  }

  public function attributeLabels(){
    return array(
      // Add it to list of labels
      'data_baz' => 'Some field'
    );
  }

  protected function beforeSave(){
    if ( !parent::beforeSave() ) {
      return false;
    }

    // Also you may create a list with names to automate append
    $this->data['baz'] = $this->data_baz;

    // And serialize data before save
    $this->data = serialize( $this->data );

    return true;
  }
}

您的表单应该是

<div class="row">
    <?php echo $form->labelEx($model, 'data_baz'); ?>
    <?php echo $form->textField($model, 'data_baz'); ?>
    <?php echo $form->error($model, 'data_baz'); ?>
</div>