Updating multiple models with one controller

Hi,

I have followed the instructions given in this page. Definitely its a great tutorial for beginners.

This url helps in inserting new records into related models

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

This url also helps in inserting new records into related models and as well as updating the related models.

Handling Related models

Is there anyway to update the related model without deleting the existing records. For example

In announcement table i have the following fields

(id,description,status)

In announcements_cities table i have the following fields

(id,announcement_id,city_id)

In cities table i have the following fields

(id,city_name)

Here HAS_MANY relations for announcements_cities model

While updating the announcement do we need to compulsorily delete the existing records as per the Larry ull tutorial or is there any other way to update as one announcement can have multiple city_id’s. I have seen there is an


updateAll

function in CActiveRecord. How we can use this in this scenario. Please help me.

Thanks.

Not sure your exact question. Are you asking if you can update the related model without doing the main? If so yes. Or all the related models at one time? Or update all in a single form just as you created it?

To update in a single form you have to change your loadModel in the controller.


public function loadModel($id)

{

	$model=MainModel::model()->with('relation')->findByPk($id);

	if($model===null)

		throw new CHttpException(404,'The requested page does not exist.');

	return $model;

}

and in your action this should be at the start


$model = $this->loadModel($id, 'MainModel');

$relatedModel = $model->relation;    OR   $model->relation->relatedAttribute;

Hi, yureshwar

I think that deleting + inserting is much more simple for updating the bridge table of MANY_MANY relation (in your case announcements_cities table).

Other way around, you have to do a considerable amount of extra coding …

  1. Retrieve all the existing rows that contains the target announcement_id.

  2. Delete all the rows among them that have a city_id which doesn’t belong to the newly selected city_id’s.

  3. Insert the new rows for the cities that belong to the newly selected city_id’s and don’t belong to the ones that are already in the existing rows.

There’s no need to do that kind of thing to torture yourself. :)

Beside that, I think the ‘id’ column of announcements_cities table is not necessary. You can make the composite primary key of announcement_id + city_id.

Thanks Enfield for trying to help me out.

Dear Softark,

Your suggestion for not to keep an id for announcement_cities is good but deleting and reinserting the new records is not an good approach as for example if you want to update an order item there it will have an problem as the order_item_id refers in billing. In this case we can do as Enfield says but for Has_Many relation that solution is not an good idea.

I too thought the way you have explained but increases the code. I am hoping that there should be way with the function ‘updateall’ with binding the params which values need to be updated. So that it will be lot more easier.

Any other suggestions in regards to this. There is an extension esaverelated which also deletes and reinserts the records and doesn’t update the old records.

Thanks for taking your time.

Hi, yureshwar,

I think I’ve got your points in the discussion.

I thought that announcements_cities table is just a bridge table for MANY_MANY relation between announcements and cities, but it is not for you.

But, then again, I don’t understand what rows you are going to update in the announcements_cities table.

What we have to do in order to update the MANY_MANY relation is deleting unnecessary rows and inserting necessary rows, there’s no need to update any rows. I don’t think ‘updateAll’ can do something here.

Hi softark,

You were rite in Many_Many relation we need to delete and we need to update the rows. Thanks for helping me out. Even we can update for particular row unless that row matches with the specified condition. But the logic will take lots of effort to make. I think as of now this will help me.

Thanks for taking your time.