How to use a single form to collect data for two or more models?

38 followers

Assume we want to use a single HTML form to collect input for both model A and model B, and we want to display input errors (if any) in the same error summary box. We can define the following action code:

public function actionCreate()
{
    $a=new A;
    $b=new B;
    if(isset($_POST['A'], $_POST['B']))
    {
        // populate input data to $a and $b
        $a->attributes=$_POST['A'];
        $b->attributes=$_POST['B'];
 
        // validate BOTH $a and $b
        $valid=$a->validate();
        $valid=$b->validate() && $valid;
 
        if($valid)
        {
            // use false parameter to disable validation
            $a->save(false);
            $b->save(false);
            // ...redirect to another page
        }
    }
 
    $this->render('create', array(
        'a'=>$a,
        'b'=>$b,
    ));
}

To add these new fields to your Create form, add your 2nd table fields no stored in a 2nd model.

A's create.php:

<?php echo $this->renderPartial('_form', array('a'=>$a, 'b'=>$b)); ?>

You usually place the specific fileds in the _form.php file if you are working off Gii created CRUD files.

<?php echo CHtml::beginForm(); ?>
 
    <?php echo CHtml::errorSummary(array($a,$b)); ?>
 
    <!-- ...input fields for $a, $b... -->
 
    <div class="row">
        <?php echo $form->labelEx($a,'a_field'); ?>
        <?php echo $form->textField($a,'a_field'); ?>
        <?php echo $form->error($a,'a_field'); ?>
    </div>
 
    <div class="row">
        <?php echo $form->labelEx($b,'b_field'); ?>
        <?php echo $form->textField($b,'b_field'); ?>
        <?php echo $form->error($b,'b_field'); ?>
    </div>
 
 
<?php echo CHtml::endForm(); ?>

The above approach can also be used if we have more than two models to deal with.

Links ΒΆ

Chinese version
Ajax Validation Version

Total 3 comments

#4754 report it
pligor at 2011/08/11 08:58am
a question on a little bit more complex implementation

Please check this question which is directly related with the solution proposed in this wiki: http://www.yiiframework.com/forum/index.php?/topic/22539-passing-posted-data-from-a-form-in-further-steps/

In case this comment is not accepted please ask me to remove it. I just wanted to link the followers of this wiki to my forum question

#4284 report it
nafa at 2011/06/21 11:55pm
help..

i already try to follow this wiki, but unfortunately its not work for me.. is there anyone can help me. thanks.. =) this is my code..

KategoriController

public function actionCreate()
    {
        $model=new Kategori;
                $sub=new Sub;

        if(isset($_POST['Kategori'], $POST['Sub']))
        {
                    // populate input data to $a and $b
                    $model->attributes=$_POST['Kategori'];
                    $sub->attributes=$_POST['Sub'];

                    // validate BOTH $a and $b
                    $valid=$model->validate();
                    $valid=$sub->validate() && $valid;

                    if($valid)
                    {
                        if($model->save(false))
                        {
                            $sub->kategori_id = $model->id;
                            $sub->save(false);
                            $this->redirect(array('view','id'=>$model->id));
                        }
                    }
                }

        $this->render('create', array(
                    'model'=>$model,
                    'sub'=>$sub,
                ));
    }

Kategori create.php

<?php echo $this->renderPartial('_form', array('model'=>$model, 'sub'=>$sub)); ?>

kategori _form.php

<div class="form">

<?php $form=$this->beginWidget('CActiveForm', array(
    'id'=>'kategori-form',
    'enableAjaxValidation'=>true,
)); ?>

    <p class="note">Fields with <span class="required">*</span> are required.</p>

    <?php echo $form->errorSummary(array($model, $sub)); ?>

    <div class="row">
        <?php echo $form->labelEx($model,'kategori'); ?>
        <?php echo $form->textField($model,'kategori',array('size'=>45,'maxlength'=>45)); ?>
        <?php echo $form->error($model,'kategori'); ?>
    </div>

        <div class="row">
        <?php echo $form->labelEx($sub,'sub'); ?>
        <?php echo $form->textField($sub,'sub',array('size'=>45,'maxlength'=>45)); ?>
        <?php echo $form->error($sub,'sub'); ?>
    </div>

    <div class="row">
                <?php echo $form->labelEx($sub,'kategori_id'); ?>
        <?php echo $form->textField($sub,'kategori_id'); ?>
                <?php echo $form->error($sub,'kategori_id'); ?>
    </div>

    <div class="row buttons">
        <?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>
    </div>

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

</div><!-- form -->
#946 report it
jmcmasterj at 2010/01/22 05:07pm
If $b has FK from $a's auto_increment PK
if($valid)  
{  
    if($a->save(false))  
    {  
        $b->a_id = $a->id;  
        $b->save(false);  
        $this->redirect(array('somewhere'));  
    }  
}

Leave a comment

Please to leave your comment.

Write new article