Wednesday, March 31, 2010

Posting with multiple models

I spent a good bit of time trying to figure out how to render multiple models in a form and have them each validate properly.

Knowing the solution, it seems quite obvious, but it took a while to track down the proper syntax.

In this example I have a custom CForm which contains a few different $model properties, in addition to the base form data.

To call the validation on multiple models in the form, simply modify any calls of
CActiveForm::validate($model);
to use an array of models as the first parameter as such:
CActiveForm::validate( array($model, $model->subModel, $model->subModel2) );

5 comments:

  1. I don't know if you read this yet:

    http://www.yiiframework.com/doc/cookbook/19/

    ReplyDelete
  2. I did read that one and found it quite helpful! My confusion came in with the ajax validation and realizing that validate actually will convert a single element into an array for processing if you don't pass in an array.

    Thanks for your feedback btw =) Much appreciate the insights!

    ReplyDelete
  3. Have you ever tried to post multiple objects of the same model in a form? Something like

    Rendered view form:

    CActiveForm {
    $a = new Class1;
    $b = new Class1;

    ...
    echo $form->textField($a, 'field1');
    ...
    echo $form->textField($b, 'field1');
    ...
    }

    I still couldnt find out a way to do it cause it seems the controller always takes only the last object of the class on the $_POST variable..

    ReplyDelete
  4. Yes, I have. You have to set it up as an array of $_POST['ObjectName'] items like so:

    (where $i is the current model count)

    echo $form->textField($a, 'field1', array('name'=>"ObjectName[$i]['field1']"));

    Then in your controller, treat the $_POST['ObjectName'] as an array and assign appropriately. Make sense?

    ReplyDelete
  5. To use your example:

    $form->textField($a, 'field1', array('name'=>'Class1[0][field1]));
    $form->textField($b, 'field1', array('name'=>'Class1[1][field1]));

    Then in the controller:

    $a = new Class1;
    $b = new Class1;
    if ( isset($_POST['Class1']))
    {
    $a->attributes = $_POST['Class1'][0];
    $b->attributes = $_POST['Class1'][1];

    // continue processing here
    }

    ReplyDelete