2015-07-11 93 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>