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

81 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 ΒΆ

Ajax Validation Version

Total 20 comments

#17722 report it
Rohit Suthar at 2014/07/17 08:07am
RE: #17720

@Vijay man don't post code here, you need to post on forum.

#17719 report it
Rohit Suthar at 2014/07/17 07:40am
RE: #17717

@Vijay May be its return NULL value so record not match.

Please do -

  1. Please check your db table fields 'code' having same words (case sensetive).
  2. You need to modified your models relational rules.

Can you open a post thread, and show me your whole code?

#17717 report it
vijay p s at 2014/07/17 07:24am
Re @Rohit Suthar

No Error but It Shows empty page..

public function actionUpdate()
    {
 
    $model=$this->loadModel($id);
    $b = Maturity::model()->findByAttributes(array('code'=>$model->code));
 
     if(isset($_POST['Add'], $_POST['Maturity'])){
 
            $model->attributes=$_POST['Add'];
            $b->attributes=$_POST['Maturity'];
 
            $valid=$model->validate();
            $valid=$b->validate() && $valid;
 
              if($valid){
                if($model->save()){
     if(!empty($b)){
 
        $b->code = $model-->code;
        $b->save();
      }
    $this->redirect(array('view','id'=>$model->Id));
}
        }
 
        $this->render('update',array(
          'model'=>$model,
          'b'=>$b,
        ));
   }
}
#17716 report it
Rohit Suthar at 2014/07/17 06:44am
RE: #17714

@Vijay It's happend becuase return of findByAttributes if no record matches or return NULL value.

$b = Maturity::model()->findByAttributes(array('code'=>$model->code));

Update your code like this -

if($model->save()){
     if(!empty($b)){
 
        $b->code = $model-->code;
        $b->save();
      }
    $this->redirect(array('view','id'=>$model->Id));
}
#17714 report it
vijay p s at 2014/07/17 06:16am
Re @Rohit Suthar

@Rohit Suthar I got this error...

Call to undefined method stdClass::getErrors() in C:\xampp\htdocs\yii\framework\web\helpers\CHtml.php on line 2002

Were I put this Code in my controller

$model->getErrors() and $b->getErrors()
#17712 report it
Rohit Suthar at 2014/07/17 02:54am
RE: #17710

@Vijay Try this update function code -

public function actionUpdate(){
 
    $model=$this->loadModel($id);
    $b = Maturity::model()->findByAttributes(array('code'=>$model->code));
 
     if(isset($_POST['Add'], $_POST['Maturity'])){
 
            $model->attributes=$_POST['Add'];
            $b->attributes=$_POST['Maturity'];
 
            $valid=$model->validate();
            $valid=$b->validate() && $valid;
 
              if($valid){
                 if($model->save()){
                    $b->save();
                    $this->redirect(array('view','id'=>$model->Id));
                 }
              }
        }
 
        $this->render('update',array(
          'model'=>$model,
          'b'=>$b,
        ));
   }
#17711 report it
Rohit Suthar at 2014/07/17 02:45am
RE: #17708

@Vijay Please update your render like this -

$this->render('update',array(
        'model'=>$model,
        'b'=>$b,
      ));

try to check errors using -

$model->getErrors() and $b->getErrors()

or you need to dump it using -

CVarDumper::dump($model->getErrors(),10,true);
#17710 report it
vijay p s at 2014/07/17 02:43am
@RE

I Have 2 tables 1.add 2.maturity. In Addcreate form having 9 fields, on that 3 fileds are need to save in the maturity table, and rest of them in the add table.

This is the concept.

SO now I finish the create() in my Addcontroller. now the info will be save in the corresponding tables. Now i need to update. already am post my update() from Addcontroller its not working.

which model ? $model or $b ? $model belongs to Add table and $b belongs to Maturity table.

my create() from addcontroller.

public function actionCreate()
    {
        $model=new Add;
        $b=new Maturity;
 
        // Uncomment the following line if AJAX validation is needed
        // $this->performAjaxValidation($model);
 
        //if(isset($_POST['Add']))
         if(isset($_POST['Add'], $_POST['Maturity']))
        {
            $model->attributes=$_POST['Add'];
            $b->attributes=$_POST['Maturity'];
 
            $valid=$model->validate();
        $valid=$b->validate() && $valid;
        if($valid)
        {
            // use false parameter to disable validation
            $model->save();
            $b->save();
            $this->redirect(array('admin'));
            // ...redirect to another page
        }
 
            //if($model->save())
            //  $this->redirect(array('view','id'=>$model->add_id));
        }
 
        $this->render('create',array(
            'model'=>$model,
            'b'=>$b,
        ));
    }

I think I gave u all details I need to finish it soon help me out.. anything needed about this issue am ready to do.

#17709 report it
KonApaz at 2014/07/17 02:29am
RE #17708

What did you mean "not return id" ?

which model ? $model or $b ?

What do you try to do ? copy data from one model to another one?

May be you have to create a post to forum to get a complete answer, giving more details.

#17708 report it
vijay p s at 2014/07/17 02:07am
Error Fix.... Now Update

@KonApaz @Rohit Suthar

Thank you for ur response. I done the create() using this article.. Before i did something went wrong but now i clearly finished..

Now i stuck with the problem, that is how can i Work with the update().

Am using the code:

public function actionUpdate($id)
        {
            $model=$this->loadModel($id);
 
            if(isset($_POST['Add'])&&isset($_POST['Maturity']))
            {
                 $model->attributes=$_POST['Add'];
 
                 $b = Maturity::model()->findByAttributes(array('code'=>$model->code));
 
                 if ($b == null) {
                   $b = new maturity;
                   $b->code = $model->code;
                 }
 
                 $b->attributes=$_POST['Maturity'];
 
 
                 if ($model->save()) {
                    $b->save();
                 }
 
                $this->render('update',array(
                    'model'=>$model,
                ));
        }
        }

When i click update button it will not return any id or something am new to this concept help me out....

#17700 report it
Rohit Suthar at 2014/07/16 02:15am
RE: #17691

May be relational rules issues. show your full code with relational array from the models.

#17693 report it
KonApaz at 2014/07/15 04:45am
RE: #17691

Hi,

check your code.

  1. did you set the $valid ?
  2. what did you mean "not loaded" ? admin or create view should be rendered.
  3. I suggest to open a forum thread with entire your code (model/viewer/controller-action) Also post the forum thread here. :)
#17691 report it
vijay p s at 2014/07/15 03:36am
@ Error

when in click create button the page is not loaded it will not be saved.... how can i save those values in the both tables.

Here is my controller..

public function actionCreate()
    {
        $model=new Add;
        $maturityModel_1 = new maturity;  // Maturity Model
    //$addressModel_2 = new Address;  // Address Model
 
        // Uncomment the following line if AJAX validation is needed
        // $this->performAjaxValidation($model);
 
         if(!empty($_POST))
        {
            $model->attributes=$_POST['Add'];
            $maturityModel_1->attributes=$_POST['Maturity'];
  if($valid)
        { 
 
               $model->save(false);
            $maturityModel_1->save(false);
            $this->redirect(array('admin'));
        }
}
 
        $this->render('create',array(
            'model'=>$model,
             'maturityModel_1'=>$maturityModel_1,
        ));
    }
#17505 report it
Tahir Yasin at 2014/06/24 05:09am
How to save multiple related models in yii [Complete Solution]
#17258 report it
dj_distinct at 2014/05/16 10:44pm
In my opinion,

Qiang's tutorial really has nothing to do with Yii (for the most part). It's pure Object-Oriented Programming in PHP. Thanks Qiang & Yang He for your support!

#16098 report it
Trydents at 2014/01/19 08:29pm
the relation is the problem

C isn't problem

the relation A with a record of B and the relation of C with another B record

#16096 report it
sensorario at 2014/01/19 05:25pm
Three models?

Just add C to the code.

#16094 report it
Trydents at 2014/01/19 03:07pm
one question

But if

A has a ralation with B

And A has a relation with C but this last one has another relation with B

how can i build the action create??

#14865 report it
Shahcheraghean at 2013/09/17 12:32am
How to do so for two or more action of one controller?

So Thank`s for this article. according to above, How to use 2 or more action of one controller in just one view file?

#14297 report it
ezekielnoob at 2013/08/02 02:58pm
How bout Bitwise operators?
if($a->validate() & $b->validate());

in this case php won't be using its typical short-circuit

Leave a comment

Please to leave your comment.

Write new article
  • Written by: qiang
  • Updated by: Yang He
  • Category: Tutorials
  • Yii Version: 1.1
  • Votes: +111 / -1
  • Viewed: 145,572 times
  • Created on: Feb 27, 2009
  • Last updated: Jun 29, 2012
  • Tags: model validation