Как установить правила проверки для пользовательских атрибутов CActiveRecord в Yii?
Я работаю над проектом 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>
Оно работает. Но есть много проблем, которые, кажется, вызваны одной и той же вещью - то, что поля формы не связаны с атрибутами / свойствами модели:
Когда я делаю поля
foo
а такжеbaz
требуется (public function rules() { return array(array('foo, baz', 'required')); }
-- недвижимость$foo
определено)foo
бахает как хотел, ноbaz
вызывает ошибку "foo не может быть пустым". Поэтому я не могу установитьdata[*]
какrequired
,Если форма недействительна и перезагружается, все
data[*]
поля пустыdata[*]
поля не помечены как обязательные.
Есть ли, чтобы решить эту проблему без изменения структуры данных? Там не будет правильного пути для этого, но, возможно, обходной путь.
1 ответ
Невозможно проверить поля таким способом. Прежде всего, если вы используете поле в модели, оно должно быть определено или существовать в таблице для активной записи. Поэтому, если вы хотите проверить такую структуру, единственный верный способ сделать это:
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>