CForm, tabular input and validation rules?

I’m trying to dynamically generate a CForm based on fields defined in a database. The code below basically does this.


class CreateAction extends CAction

{

    public function run()

    {

        $model=new Profile;

        $elements = array();

        $fields = ProfileField::model()->findAll(array(

                    'order'=>'position',

                    ));

        foreach ($fields as $i=>$field)

        {

            array_push($elements,array('name'=>'test','label'=>$field->label,'type'=>$field->type,'value'=>''));

        }

        $buttons = array('create'=>array('type'=>'submit','label'=>yii::t('core','Save')));

        $config = array('title' => yii::t('core','Create profile'), 'elements' => $elements, 'buttons' => $buttons);

        $form = new CForm($config, $model);

        if ($form->submitted('create') && $form->validate())

        {

            if(isset($_POST['Profile']))

            {

                $model->setScenario('create');

                $model->attributes=$_POST['Profile'];

                if($model->save())

                    $this->controller->redirect(array('view','id'=>$model->id));

            }

        }

        $this->controller->render('create',array('form'=>$form));

    }

}

Unfortunately, all the input fields generated in this form are the same. They all look like this:


<input value="" name="Profile[test]" id="Profile_test" type="text" />

This is easily explained by the fact that all my elements are currently called ‘test’, which I have declared as a variable in the model and set as a ‘safe’ attribute in the model’s rules. In line with the Collecting Tabular Input guide, however, each input field should have a unique identifier. The name definition should be something like this to do so:


'name'=>"[$i]test"

Problem is that I’ve been unable to figure out how to use variables in the rule definition. These don’t seem to work:


public function rules()

    {

        return array(

            array("test, []test, [*]test", 'safe'),

        );

    }

Without a rule, none of the fields are displayed. I actually want to apply a custom rule once I get this to work, but are testing with ‘safe’ for now.

How should I do this?

You would make things much easier on yourself if you just used an actual database table (just create a test one with a variety of column types). That way, you won’t have to worry about creating “fake” columns, and trying to get them to display.

Additionally, you can get the column schema info like so (once using a db table):




$model->metaData->tableSchema->columns



True. I do however have good reasons not to want to do so for this site I’m building.

The essence of my question though is: how do you define a rule for tabular input fields?

First, tabular input is intended for submitting multiple model instances. In your case it seems like you want to submit one model instance, populated with a set of custom fields (a subset of the db record). You want to add custom rules by the custom field names.

Obviously you have to generate unique field names instead of ‘name’=>‘test’. The field definition probably would have to be reread on submit.

One idea would be to dynamically merge your custom rules to the rules declared inside rules() in your custom model. You should be able to do whatever you prefer as long as rules() returns an array with appropriate contents (for a particular model instance).

(not tested)

/Tommy