Dynamic User Profile management in yii?

494 views Asked by At

I have two tables in database profile_fields and profile_fields_values.

Table profile_fields has columns

  • id
  • fieldname
  • fieldtitle
  • fieldtype
  • orderby
  • required
  • published

Table profile_field_values has columns

  • id
  • field_id
  • user_id
  • field_value

Here I have to create a dynamic profile management.

How do I show dynamic forms in Yii?

2

There are 2 answers

3
Pentium10 On

You need to use Form Builder, it has plenty of example how to construct your form using an array. It also supports sub-forms. Just follow the examples from the linked tutorial, content it's to long to be referenced here.

Update:

class LoginForm extends CFormModel
{
    public $username;
    public $password;
}

$form = new LoginForm();
$form->validatorList->add(
    CValidator::createValidator('required', $form, 'username, password')
);

or another example:

class SomeModel
{
 public $orders;
 public function rules()
 {
  return array(
   array('orders', 'validateOrders'),
  );
 }

 public function validateOrders($attribute, $params)
 {
  foreach($this->orders as $order)
   if (empty($order)) {
    $this->addError('orders', 'There is an empty order');
    break;
   }
 }
}

A more broader example is on forum.

0
Gaurav Parashar On
I am trying to build this dynamic profile management let me know my approach is my approach is right?

firstly i have created a input form(_form) where user can input fieldtype,fieldname,fieldtitle and field default value and etc which can be save in database table (profile_fields).In this fieldtype is bydefault set and user choose it from dropdownlist As like in the below form.

<?php
/* @var $this ProfileManagerController */
/* @var $model ProfileFields */
/* @var $form CActiveForm */

?>

<div class="form">

<?php $form=$this->beginWidget('CActiveForm', array(
    'id'=>'profile-fields-form',
    'enableAjaxValidation'=>false,
)); ?>

    <p class="note">Fields with <span class="required">*</span> are required.</p>
    <?php echo $form->errorSummary($model); ?>

    <div class="row">
        <?php echo $form->labelEx($model,'location'); ?>
        <?php echo $form->dropDownList($model,'location',CHtml::listData(Countries::model()->findAll('',array('orderby' => 'countryName ASC')),'countryCode','countryName'), array('empty' => array("*" => 'For All Countries'))); ?>
        <?php echo $form->error($model,'location'); ?>
    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'profile_type'); ?>
        <?php echo $form->dropDownList($model,'profile_type',Yii::app()->params['userRoles'], array('empty' => array("*" => 'For All users')), array($model->profile_type)); ?>
        <?php //echo $form->dropDownList($model, 'profile_type', Yii::app()->params['userRoles'], array($model->profile_type)); ?>
        <?php echo $form->error($model,'profile_type'); ?>
    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'section'); ?>
        <?php echo $form->dropDownList($model,'section',array('profile'=>'profileSection','basicdetails'=>'BasicDetails','contactdetails'=>'ContactDetails','imagedetails'=>'ImageDetails','clientdetails'=>'ClientDetails','tagdetails'=>'TagDetails','otherdetails'=>'OtherDetails','alldetails'=>'AllDetails')); ?>
        <?php echo $form->error($model,'section'); ?>
    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'field_name'); ?>
        <?php echo $form->textField($model,'field_name',array('size'=>60,'maxlength'=>255)); ?>
        <?php echo $form->error($model,'field_name'); ?>
    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'field_title'); ?>
        <?php echo $form->textField($model,'field_title',array('size'=>60,'maxlength'=>255)); ?>
        <?php echo $form->error($model,'field_title'); ?>
    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'field_type'); ?>
        <?php echo $form->dropDownList($model,'field_type',array('text' => 'Text','date' => 'Date','email' => 'Email', 'radio' => 'Radio','multiselect' => 'Multi Select Dropdown List','file'=>'File','checkbox'=>'CheckBox','hidden'=>'Hidden','select'=>'Dropdownlist','password'=>'Password','checkboxlist'=>'Checkboxlist','radiolist'=>'Radiolist','textarea'=>'TextArea'),array('options' => array($model->field_type => array('selected' => true)))); ?>
        <?php echo $form->error($model,'field_type'); ?>
    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'field_default_value'); ?>
        <?php echo $form->textArea($model,'field_default_value',array('rows'=>6, 'cols'=>50)); ?>
        <?php echo $form->error($model,'field_default_value'); ?>
    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'required'); ?>
          <?php echo $form->dropDownList($model, 'required', array('1' => 'Yes', '0' => 'No')); ?>
        <?php echo $form->error($model,'required'); ?>
    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'published'); ?>
          <?php echo $form->dropDownList($model, 'published', array('1' => 'Yes', '0' => 'No')); ?>
        <?php echo $form->error($model,'published'); ?>
    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'order_by'); ?>
        <?php echo $form->textField($model,'order_by'); ?>
        <?php echo $form->error($model,'order_by'); ?>
    </div>
    <div class="row buttons">
        <?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>
    </div>

<?php $this->endWidget(); ?>

</div><!-- form -->
secondly I have created a view index file which will show dynamically what type of fieldstypes and fieldsname and field title are set by the user in profile_field table and call the extension created by me and then another  user can input accordingly .and these values are save in profile_field_values table .
----------index file---------------


<div class="form">

    <?php
    $form = $this->beginWidget('CActiveForm', array(
        'id' => 'completeProfile-form',
        'htmlOptions' => array('enctype' => 'multipart/form-data'),
        'enableAjaxValidation' => false,
        'clientOptions' => array('validataOnSubmit' => true),
        'enableClientValidation' => true,        
    ));
    ?>
    <?php
    if (!empty($field_data)) {
        foreach ($field_data as $field) { 
            $selectedOptions = '';
            $def_value='';
            $field_name = $field->field_name; // required field
            $field_type = $field->field_type; // required field
            $field_id = $field->id; // required field

            //for validation 
            $req = $field->required == 1 ? 'required' : ''; // required if using validation
            $email = $field->field_type == 'email' ? 'email' : ''; // required if using validation
            $password = $field->field_type == 'password' ? 'password' : ''; // required if using validation
            $class = array($req, $email, $password); // class must be array type, if no class found, send empty array
            //values present in  ProfileFieldsValues to populate
            $value = ProfileFieldsValues::model()->findByAttributes(array('user_id' => Yii::app()->user->id, 'field_id' => $field->id));
            // set html options
            $htmlOptions = array();
            $htmlOptions['class'] = implode(" ", $class);
            $htmlOptions['value'] = $value ? $value->field_value : '';
            // field array - Must SET
            $fieldArray = array();
            $fieldArray['model'] = $field;
            $fieldArray['form'] = $form;
            $fieldArray['field_type'] = $field_type;
            $fieldArray['field_name'] = $field_name;
            $fieldArray['field_id'] = $field_id;
            $fieldArray['default_value'] = $value ? $value->field_value : $field->field_default_value;

            //If input type field is dropdowlist for selecttion
            if($field_type == 'select' ){
                if(!empty($field->field_default_value)){
                    $my_string = preg_replace(array('/\n/'), '#PH#', $field->field_default_value );
                    $my_array = explode('#PH#', $my_string);
                    foreach($my_array as $my_arr){
                            $def=explode('|',$my_arr);
                            $def_value[$def[0]]=$def[1];
                    }
                     $fieldArray['select_box_array']=$def_value;
                }else{
                     $fieldArray['select_box_array'] =$country;
                }
                $htmlOptions['prompt'] = 'SELECT ANY';
                $value ? $htmlOptions['options']=array($value->field_value=>array('selected'=>'true')): $htmlOptions['prompt'] = 'SELECT ANY';
            }
            //if input type field is multiple select dropdownlist
            if( $field_type == 'multiselect'){
                if(!empty($field->field_default_value)){
                    $my_string = preg_replace(array('/\n/'), '#PH#', $field->field_default_value );
                    $my_array = explode('#PH#', $my_string);
                    foreach($my_array as $my_arr){
                    $def=explode('|',$my_arr);
                    $def_value[$def[0]]=$def[1];
                    }
                    $fieldArray['select_box_array']=$def_value;
                }else{
                    $fieldArray['select_box_array'] =$country;
                }
                $htmlOptions['prompt'] = 'SELECT Multiple';
                if(!empty($value)){
                $field_valu= explode(',',$value->field_value); 
                foreach($field_valu as $eachValue){
                    $selectedOptions[$eachValue] = array('selected'=>'selected');
                 }
                $htmlOptions['options']= $selectedOptions;
                }

            }
            // if input type field is radio button
            if ($field_type == 'radiolist') {
                $fl = ProfileFieldsValues::model()->findByAttributes(array('field_id' => $field->id, 'user_id' => Yii::app()->user->id));                
                if(!empty($field->field_default_value)){
                $my_string = preg_replace(array('/\n/'), '#PH#', $field->field_default_value );
                $my_array = explode('#PH#', $my_string);
                foreach($my_array as $my_arr){
                    $def=explode('|',$my_arr);
                    $def_value[$def[0]]=$def[1];
                }
                 $fieldArray['radio_box_array']=$def_value;
                }else{
                 $fieldArray['radio_box_array'] =array('hello','bye');
                }

                $value = $fl ? $fl->field_value : 0;
                $htmlOptions = array('labelOptions' => array('style' => 'display:inline'), 'separator' => ' ','value' => $value);
            }
            //if input type field is checkbox list
            if ($field_type == 'checkboxlist') {
                $fl = ProfileFieldsValues::model()->findByAttributes(array('field_id' => $field->id, 'user_id' => Yii::app()->user->id));
                if(!empty($field->field_default_value)){
                    $my_string = preg_replace(array('/\n/'), '#PH#', $field->field_default_value );
                    $my_array = explode('#PH#', $my_string);
                    foreach($my_array as $my_arr){
                        $def=explode('|',$my_arr);
                        $def_value[$def[0]]=$def[1];
                    }
                    $fieldArray['check_box_array']=$def_value;
                }else{
                    $fieldArray['check_box_array'] =array('hello','bye');
                }

                $value = $fl ? (array)explode(",",$fl->field_value) : array(0);                                
                $htmlOptions = array('labelOptions' => array('style' => 'display:inline'), 'separator' => ' ','value' => $value );
            }
            //if input type field is file
            if ($field_type == 'file') {
                $files = ProfileFieldsValues::model()->findByAttributes(array('field_id' => $field->id, 'user_id' => Yii::app()->user->id));
                if(isset($files->field_value)){
                    echo CHtml::image(Yii::app()->request->baseUrl . '/images/user_images/' .$files->field_value, 'Image', array('class' => 'img-polaroid', 'width' => 200)); 
                }
            }
            $fieldArray['htmlOptions'] = $htmlOptions;
                if ($field->published == '1') { 
                        if($field->field_type == 'checkbox' || $field->field_type == 'radio' ){ ?>
                        <div class="row">   
                            <?php $this->widget('ext.dynamicFields.EDynamicFields', $fieldArray); ?>
                            <?php echo $field->field_title; ?>
                            <?php echo $form->error($field, $field->field_title); ?>
                        </div>
                        <?php }else{ ?>
                        <div class="row">   
                        <?php echo $form->labelEx($field, $field->field_title); ?>
                        <?php $this->widget('ext.dynamicFields.EDynamicFields', $fieldArray); ?>
                        <?php echo $form->error($field, $field->field_title); ?>
                        </div>
                        <?php } ?>
                <?php } ?>
            <?php } ?>
            <div class="row buttons">
                <?php echo CHtml::submitButton('Submit'); ?>
            </div>

        <?php

    }
     $this->endWidget();
    ?>

</div><!-- form -->
<?php Yii::app()->clientScript->registerScriptFile(Yii::app()->getBaseUrl(true) . '/js/jquery.validate.js'); ?>
<script type="text/javascript">

    $("#completeProfile-form").validate({
    });
</script>


I have created a extension for various input type fields like
1.text
2.email textbox
3.hidden input type field
4.textarea
5.dropdownlist 
6. multiple select dropdownlist
7.password textfield            
8.file
9.radiolist
10.radio button
11 checkbox
12checkboxlist
13 date field             
   <?php

/**
 * Description of EDynamicFields
 * It will show dynamic fields
 *
 * @author Gaurav Parashar
 */
class EDynamicFields extends CWidget {

    public $field_type;
    public $field_name;
    public $field_id;
    public $default_value;
    public $select_box_array = array();
    public $radio_box_array = array();
    public $check_box_array = array();
    public $htmlOptions = array();
    public $model;
    public $form;
    public $select;

    public function run() {
        switch ($this->field_type) {
            case 'text':
                echo $this->form->textField($this->model, "field_name[$this->field_type][$this->field_id]", $this->htmlOptions);
            break;
            case 'email':
                echo $this->form->textField($this->model, "field_name[$this->field_type][$this->field_id]", $this->htmlOptions);
            break;
            case 'hidden':
                echo $this->form->hiddenField($this->model, "field_name[$this->field_type][$this->field_id]", $this->default_value);
            break;
            case 'textarea':
                echo $this->form->textArea($this->model, "field_name[$this->field_type][$this->field_id]", $this->htmlOptions);
            break;
            case 'select':
                echo $this->form->dropDownList($this->model, "field_name[$this->field_type][$this->field_id]", $this->select_box_array, $this->htmlOptions);
            break;
            case 'password':
                echo $form->passwordField($model,'password',$this->htmlOptions);
                break;
            case 'multiselect':
                $newarr = array_merge($this->htmlOptions, array('multiple' => 'multiple'));
                echo $this->form->dropDownList($this->model, "field_name[$this->field_type][$this->field_id]", $this->select_box_array, $newarr);
            break;
            case 'file':
                echo $this->form->fileField($this->model, "field_name[$this->field_type][$this->field_id]" ,$this->htmlOptions);
            break;
            case 'radio':
                echo $this->form->radioButton($this->model, "field_name[$this->field_type][$this->field_id]", $this->htmlOptions);
            break;
            case 'radiolist':
                echo CHtml::radioButtonList("ProfileFields[field_name][$this->field_type][$this->field_id]",$this->htmlOptions['value'],$this->radio_box_array,$this->htmlOptions);
            break;
            case 'checkbox':
                echo $this->form->checkBox($this->model, "field_name[$this->field_type][$this->field_id]", $this->htmlOptions);
            break;
            case 'date':
                 $this->widget('zii.widgets.jui.CJuiDatePicker', array(
                                'attribute' => "field_name[$this->field_type][$this->field_id]",
                                'model' => $this->model,
                                'htmlOptions'=>array(
                                'class'=>'required',
                                ),    
                                'options' => array(
                                        'dateFormat' => 'yy-mm-dd',
                                        'maxDate' => 'new Date()', // One month ahead
                                        //'minDate' => '-50y', // Today
                                        'changeMonth' => true,
                                        'changeYear' => true,
                                        'yearRange'=>'2000:2099',
                                        'minDate' => '2000-01-01',      // minimum date
                                        'maxDate' => '2099-12-31',

                                )
                ));
            break;
            case 'checkboxlist':
                    echo CHtml::checkBoxList("ProfileFields[field_name][$this->field_type][$this->field_id]",$this->htmlOptions['value'],$this->check_box_array,$this->htmlOptions);
            break;
        }
    }

}