2015-07-11 89 views
0

我正在与数据库中的Yii的项目,包含一个表,其中几乎所有它的数据保存在一个字段作为JSON(它的疯狂,但它是如此,因为它是):如何在Yii中为自定义CActiveRecord属性设置验证规则?

id  INTEGER 
user_id INTEGER 
data LONGTEXT 

这种“JSON场” data具有以下结构,并含有特别的图像:

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

显示它是没有问题的,但现在我想以使数据ediable。我的表单看起来像这样:

<?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. 当我做出场foo和所需bazpublic function rules() { return array(array('foo, baz', 'required')); } - 属性$foo被定义)foo bahaves如所愿,但baz导致“foo不能为空”错误。所以我不能将data[*]设置为required

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

  3. data[*]字段未按要求标记。

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

回答

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>