suggestions on how to elegantly handle the input of simple child-relationship models

I commonly run into the scenario where I have a top-level model (i.e. User) that then has one or more child models (i.e. Award, Photo, Event). Typically the child model table structures are very simple consisting of a primary key (id), a foreign key (userId) and a label (awardLabel). It seems most efficient that the user creating or updating a User model manages all this information on the same page. However, I don’t see a clear method for this to be done in Yii. I’ve searched and read the few postings that talk about passing multiple models to a view but none of these pages go into complete detail of a solution. Additionally, should the views be constructed within each model’s directory (i.e. views/User/_form.php, views/Award/_form.php, views/Photo/_form.php, views/Event/_form.php) and then combined in the views/User/create.php or views/User/update.php file?

Lastly, these simple form inputs seem perfect for Ajax-style submission where the entire page doesn’t refresh–just the DIV containing the list of Awards, for example. I’ve never done an Ajax form, with or without Yii.

Can anyone give an example that provides a solutions to the scenario above? If it is done with Ajax submission that is a huge bonus!

Try CForm with sub forms: http://www.yiiframework.com/doc/guide/form.builder#specifying-sub-form

Thanks! I’ve read through the documentation and am still having troubles. Any help you can offer is greatly appreciated.

My particular data structure is this:

  • the parent model, Staff, contains basic personal information (name, phone, etc)

  • there are many child models for Staff that are optional (zero to many records)

Education is one such child model. It is a simple text field in which the user can input information about when/where they went to school. The Education model has a (hidden) field, staffId, which links it back to the parent model, Staff.

I’d like the input to be a single page with multiple fieldsets. The first fieldset would have all necessary fields to complete the Staff model. The next fieldset would be for Education listing all the rows associated with the particular staffer. The first row of this table would be an editable field such that the user can add a new Education listing.

So, I need to populate a form using multiple models, and, after submission, create/update/delete the necessary information in multiple models.

The output of this is a form correctly populated with the Staff model information. However, the Education model fields are nowhere to be found? I realize in actionUpdate() I am not passing the array of Education models ($education) to the CForm object ($form)…that is because I don’t know how to pass it? I’ve tried looking at the CForm code but don’t see where it accepts multiple models.

Here is the code I have so far:

protected/controller/StaffController.php:




public function actionUpdate()

{

	$staff=$this->loadModel();

	$education=education::model()->findAllByAttributes(array('staffId'=>$staff->ID));

	

	$form=new CForm('application.views.staff.staffForm',$staff);


	if(isset($_POST['staff']))

	{

		$model->attributes=$_POST['staff'];

		$model->updateTS = date('Y-m-d H:i:s');

		if($model->save())

			$this->redirect(array('view','id'=>$model->ID));

	}




	$this->render('inputStaff', array('form'=>$form));

}



protected/views/staffForm.php:




<?php

  return array(

    'elements'=>array(

        'staff'=>array(

            'type'=>'form',

            'title'=>'Staff Information',

            'elements'=>array(

                'id'=>array(

                    'type'=>'hidden',

                ),

                'name'=>array(

                    'type'=>'text',

                ),

                'phone'=>array(

                    'type'=>'text',

                ),

                'fax'=>array(

                    'type'=>'text',

                ),

                'email'=>array(

                    'type'=>'text',

                ),

                'website'=>array(

                    'type'=>'text',

                ),

            ),

        ),

        'education'=>array(

            'type'=>'form',

            'title'=>'Education Information',

            'elements'=>array(

                'id'=>array(

                    'type'=>'hidden',

                ),

                'staffId'=>array(

                    'type'=>'hidden',

                ),

                'label'=>array(

                    'type'=>'text',

                ),

            ),

        ),

    ),

  );

?>



protected/views/inputStaff.php:




<h1>Staff</h1>

 

<div class="form">

<?php 

    echo $form; 

?>

</div>



Okay… I figured out how to pass multiple models to CForm. However, now I’m having to create (query) the model from within a “view” file…this seems contrary to MVC structure. Does anyone else thing you should be able to pass multiple models when instantiating an object of type CForm?

For example (within your controller method):




$multipleModels=array(myModel01::model()->findByPk($id1),myModel02::model()->findByPk($id2));


$myForm=new CForm('application.views.staff.staffForm',$multipleModels);



Here is a new version of staffForm.php with the added key/value pair…

protected/views/staff/staffForm.php:




<?php


  $staff=staff::model()->findByPk($_GET['id']);


  $education=education::model()->findByAttributes(array('staffId'=>$staff->ID));


  return array(

    'elements'=>array(

        'staff'=>array(

            'type'=>'form',

            'model'=>$staff,                 <-- YOU NEED THIS!

            'title'=>'Staff Information',

            'elements'=>array(

                'name'=>array(

                    'type'=>'text',

                ),

                'phone'=>array(

                    'type'=>'text',

                ),

                'fax'=>array(

                    'type'=>'text',

                ),

                'email'=>array(

                    'type'=>'text',

                ),

                'website'=>array(

                    'type'=>'text',

                ),

            ),

        ),

        'education'=>array(

            'type'=>'form',

            'model'=>$education,               <-- YOU NEED THIS!

            'title'=>'Education Information',

            'elements'=>array(

                'label'=>array(

                    'type'=>'text',

                ),

            ),

        ),

    ),

    'buttons'=>array(

        'submit'=>array(

            'type'=>'submit',

            'label'=>'submit',

        ),

    ),

  );

?>



You can do it after instantiation, in the controller. See [SOLVED] How to associate model with sub-form?