Hi,
my database structure looks this way:
User -> basic user data (user_id, user_nick, etc.)
User2Data -> optional (extended) Data (auto_id, user_id, datatype_id, data, view_flag [0 = no one, 1 = everyone is allowed to see this data])
Datatypes -> Datatypes (datatype_id, datatype, type [varchar, integer, email etc.], required_flag, readonly_flag (User is not allowed to change his name)
In my ProfileController I build in my editAction an new FormModel: DynamicFormModel wich looks like this:
class DynamicFormModel extends CFormModel {
public $elements = array();
public $models = array();
public function rules() {
$required = array();
$intOnly = array();
$eMail = array();
$varChars = array();
$output = array();
foreach($this->models as $k => $e) {
if($e['required_flag']) {
$required[] = $e['datatype'];
}
if($e['type']=='integer') {
$intOnly[] = $e['datatype'];
}
if($e['type']=='varchar') {
$varChars[] = $e['datatype'];
}
if($e['type']=='eMail') {
$eMail[] = $e['datatype'];
}
//print_r($e);
}
if(!empty($eMail)) {
$output[] = array(implode(', ', $eMail), 'email', 'on' => implode(', ', $eMail), 'on' => implode(', ', $eMail));
}
if(!empty($varChars)) {
$output[] = array(implode(', ', $varChars), 'length', 'max' => 200, 'on' => implode(', ', $varChars));
}
if(!empty($intOnly)) {
$output[] = array(implode(', ', $intOnly), 'numerical', 'integerOnly'=>true, 'on' => implode(', ', $intOnly));
}
if(!empty($required)) {
$output[] = array(implode(', ', $required), 'required', 'on' => implode(', ', $required));
}
return $output;
}
public function __get($name) {
//if(isset(($name,)) {
if(is_numeric($name)) {
foreach($this->elements as $e) {
if($e['datatype'] == $name) {
return $e['data'].'_cb';
}
}
//return $this->$name;
} else {
foreach($this->elements as $e) {
if($e['datatype'] == $name) {
return $e['data'];
}
}
//return $this->$name;
}
//}
}
}
?>
In my Datatypes-Model I have a relation to my User2Data-Model, but couldn’t it handle into the view so I a foreach where i put the user2Data object into a new field called “data”.
So in my ProfilController I set the following:
public function actionEdit() {
$dynamicForm = new DynamicFormModel();
$dynamicForm->models = Datatyp::model()->findAll();
$attr['user_id'] = $this->user_id;
foreach($dynamicForm->models as $k => $v) {
$attr['datatyp_id'] = $v['datatyp_id'];
$dynamicForm->models[$k]['daten'] = User2Data::model()->findByAttributes($attr);
}
if(isset($_POST['User2Data'])) {
/*
* I don`t really know, what to do here ?
* Any help?
*/
$dynamicForm->attributes = $_POST['User2Data'];
if($dynamicForm->validate()){
// TODO
} else {
$this->render('einstellungen', array('dynamicForm'=>$dynamicForm));
}
} else {
$this->render('einstellungen', array('dynamicForm'=>$dynamicForm));
}
}
My view looks this way:
<?php
$form=$this->beginWidget('CActiveForm', array(
'id' => 'register-form',
'action' => $this->createUrl('profile/edit'),
'enableClientValidation' => true,
'enableAjaxValidation' => true,
'clientOptions' => array(
'validateOnSubmit'=>true,
),
));
?>
<fieldset>
<label><?php echo Yii::t('profile', 'info_text'); ?></label>
<br />
<?php
foreach($dynamicForm->models as $e => $mod) {
$readonly = ($mod['readonly_flag']==1) ? array('readonly'=>true) : array();
?>
<div class="row">
<div class="three columns">
<?php echo $form->label($dynamicForm,Yii::t('profile',$mod['datatype'])); ?>
</div>
<div class="seven columns">
<?php echo $form->textField($mod->data,"[$e]data", $readonly); ?>
<?php echo $form->hiddenField($mod->data,"[$e]datatyp_id", $readonly); ?>
</div>
<div class="two columns">
<?php echo $form->checkBox($mod->data,"[$e]view_flag"); ?>
<?php echo $form->label($dynamicForm,Yii::t('profile','show'),array('class'=>'default')); ?>
</div>
</div>
<?php
}
echo CHtml::submitButton(Yii::t('profile','save'), array("class" => "button"));
?>
</fieldset>
<?php
$this->endWidget();
?>
So during my procedure from "wtf" to "i hate the world" i had the following questions / problems.
Is there an easy understanding way to set attributes on the fly for a CFormModel? As you can see i tried to set rules dynamicallly in my DynamcFormModel. (Same question: Can I generate dynamically rules?)
Is there a better solution for my db-layout? My intention is to have a db-table where i can define datatypes (e.g. ‘Skype’, ‘Facebook’, ‘favourite Movies’, … etc.) which the user can add / edit in his profile withput updating my models everytime. In the Past i had all this information in my user-table with an view_flag for die seperate information (user_id, user_nick, skype, skype_view_flag, facebook, facebook_view_flag, … , etc)
I hope you understand my bad english and can help me - have a nive weekend
PS: tell me, if you need some more information.