How to use Multiple instances of the same model in the same form

You are viewing revision #5 of this wiki article.
This version may not be up to date with the latest version.
You may want to view the differences to the latest version.

next (#6) »

When i had created this functionality then i found some difficulties and not got much idea from wiki and forums. so, i think this will be useful for newbie users and save time of other developers when create related functionality. I refer Collecting Tabular Input tutorial but not got clear idea for create/update.

Here in my demo i had two tables as, User(table) can have multiple address ( home, company ) which comes from Address(table)

Model generated by gii and no any change in model.

User Table
---id
---name
---surname
---email
---home_address_id ( data refer to Address table )
---company_address_id ( data refer to Address table )
Address Table
---id
---street
---city
---state

Developer can also use loop for multiple instances here in my demo i explained with two.

Create Controller
public function actionCreate()
	{
		$model=new User;  // User Model
		$addressModel_1 = new Address;  // Address Model
		$addressModel_2 = new Address;  // Address Model
		
		if(!empty($_POST))
		{
			$addressModel_1->attributes=$_POST['Address'][1];  // Set attribute for home address
			$addressModel_2->attributes=$_POST['Address'][2];  // Set attribute for company address
			$model->attributes=$_POST['User'];  // Set attribute for user data
					
			$valid=$addressModel_1->validate();
       		$valid=$addressModel_2->validate() && $valid;
       		$valid=$model->validate() && $valid;
			
			if($valid)
			{ 
				$addressModel_1->save();
				$homeAddressId = $addressModel_1->id;
							
				$addressModel_2->save();
				$companyAddressId = $addressModel_2->id;
				
				$model->home_address_id = $homeAddressId;  // Set saved address as user home id
				$model->company_address_id = $companyAddressId;  // Set saved address as user company id
				$model->save();
				$this->redirect(array('view','id'=>$model->id));
			}
		}
		$this->render('create',array(
			'model'=>$model,'addressModel_1'=>$addressModel_1,'addressModel_2'=>$addressModel_2,
		));
	}
Update Controller
public function actionUpdate($id)
	{		
		$model=User::model()->findByPk($id);  // Load user data in model		
		$addressModel_1=Address::model()->findByPk($model->home_address_id);  // Load address data in addressModel_1		
		$addressModel_2=Address::model()->findByPk($model->company_address_id);  // Load address data in addressModel_2

		if(!empty($_POST))
		{
			$addressModel_1->attributes=$_POST['Address'][1];  // Set attribute for home address
			$addressModel_2->attributes=$_POST['Address'][2];  // Set attribute for company address
			$model->attributes=$_POST['User'];  // Set attribute for user data
					
			$valid=$addressModel_1->validate();
       		$valid=$addressModel_2->validate() && $valid;
       		$valid=$model->validate() && $valid;
			
			if($valid)
			{ 		
				$addressModel_1->save();
				$addressModel_2->save();
				$model->save();
			}
		}
		$this->render('update',array(
			'model'=>$model,'addressModel_1'=>$addressModel_1,'addressModel_2'=>$addressModel_2,
		));
	}
View Form

For create and update same page rander as _form, from below view code you can get idea how i pass model and set attribute name for elements..

<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
	'id'=>'user-form',
	'enableAjaxValidation'=>false,
)); ?>

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

	<div class="row">
		<?php echo $form->labelEx($model,'name'); ?>
		<?php echo $form->textField($model,'name',array('size'=>50,'maxlength'=>50)); ?>
		<?php echo $form->error($model,'name'); ?>
	</div>
	<div class="row">
		<?php echo $form->labelEx($model,'surname'); ?>
		<?php echo $form->textField($model,'surname',array('size'=>50,'maxlength'=>50)); ?>
		<?php echo $form->error($model,'surname'); ?>
	</div>
	<div class="row">
		<?php echo $form->labelEx($model,'email'); ?>
		<?php echo $form->textField($model,'email',array('size'=>50,'maxlength'=>50)); ?>
		<?php echo $form->error($model,'email'); ?>
	</div>
	
	//////////////////////////////////////////////////////
	<h2>Home Address Below</h2>	

	<div class="row">
		<?php echo $form->labelEx($addressModel_1,'[1]street'); ?>
		<?php echo $form->textField($addressModel_1,'[1]street'); ?>
		<?php echo $form->error($addressModel_1,'[1]street'); ?>
	</div>
	<div class="row">
		<?php echo $form->labelEx($addressModel_1,'[1]city'); ?>
		<?php echo $form->textField($addressModel_1,'[1]city'); ?>
		<?php echo $form->error($addressModel_1,'[1]city'); ?>
	</div>	
	<div class="row">
		<?php echo $form->labelEx($addressModel_1,'[1]state'); ?>
		<?php echo $form->textField($addressModel_1,'[1]state'); ?>
		<?php echo $form->error($addressModel_1,'[1]state'); ?>
	</div>
	
	//////////////////////////////////////////////////////
	<h2>Company Address Below</h2>
	
	<div class="row">
		<?php echo $form->labelEx($addressModel_2,'[2]street'); ?>
		<?php echo $form->textField($addressModel_2,'[2]street'); ?>
		<?php echo $form->error($addressModel_2,'[2]street'); ?>
	</div>
	<div class="row">
		<?php echo $form->labelEx($addressModel_2,'[2]city'); ?>
		<?php echo $form->textField($addressModel_2,'[2]city'); ?>
		<?php echo $form->error($addressModel_2,'[2]city'); ?>
	</div>	
	<div class="row">
		<?php echo $form->labelEx($addressModel_2,'[2]state'); ?>
		<?php echo $form->textField($addressModel_2,'[2]state'); ?>
		<?php echo $form->error($addressModel_2,'[2]state'); ?>
	</div>

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

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

</div><!-- form -->
Demo

The demo some what look like,

All field validation

There will be single entry in User table and two entry in Address table ( for home and company ) same data update on update scenario.

I hope this will help to many...

10 3
23 followers
Viewed: 93 173 times
Version: Unknown (update)
Category: How-tos
Written by: kiran sharma
Last updated by: Maurizio Domba Cerin
Created on: Aug 1, 2012
Last updated: 12 years ago
Update Article

Revisions

View all history