2015-07-11 1 views
0

Je travaille sur un projet Yii avec une base de données, qui contient une table, où la quasi-totalité ses données sont enregistrées dans un champ JSON (il est fou, mais il en est ainsi car il est):Comment définir des règles de validation pour les attributs CActiveRecord personnalisés dans Yii?

id  INTEGER 
user_id INTEGER 
data LONGTEXT 

Ce champ « JSON » data a la structure suivante et contient, entre autres, une image:

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

il n'y a pas affiche-problème, mais maintenant je veux faire le ediable de données. Ma forme ressemble à ceci:

<?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> 

Cela fonctionne. Mais il y a de multiples problèmes, qui semblent être causés par la même chose - qu'il forme les champs ne sont pas référencés aux attributs modèle/propriétés:

  1. Quand je fais des champs foo et baz nécessaires (public function rules() { return array(array('foo, baz', 'required')); } - la propriété $foo est définie) foo bahaves comme souhaité, mais baz provoque une erreur "foo ne peut pas être vide". Donc, je ne peux pas définir data[*] comme required.

  2. Si le formulaire est pas valide et se rechargées, tous les champs sont vides data[*]. Les champs data[*] ne sont pas marqués comme requis.

Y a-t-il une solution à ce problème sans changer la structure de la base de données? Il n'y aura pas de façon correcte, mais peut-être une solution de contournement.

Répondre

0

Il est impossible de valider des champs de cette manière. Tout d'abord, si vous utilisez un champ dans le modèle, il doit être défini ou exister dans la table pour l'enregistrement actif. Donc, si vous voulez valider cette structure la seule bonne façon de le faire:

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; 
    } 
} 

Et votre formulaire devrait ressembler à

<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>