Need help with related tabular input

I have two tables with a one-to-many relationship.

The related table has a tabular input form to collect multiple instances.

The problem I’m having is this:

If I omit any required fields from my primary table, I get an error message - this is good.

If I omit any required fields from the dependent table, it saves the primary and redirects. Not good.

I’ve read the wiki and forum about multimodel forms but this doesn’t really apply to my situation. The problem is that I need to make sure that both the primary and related table have $_POST data and if not, show the required error.

How do you do multiple model forms with tabular input?

I’ve tried to change this code to use the $valid=$model->validate() && $valid workflow suggested in the wiki - but the problem is that I don’t know how to make this work in a 1:Many situation.

My code:




	if(isset($_POST['Inspection'])) {

		//Manually assign model attributes since not coming from user form. Skipping massive assignment

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

		$model->userId=Yii::App()->user->id;

		$model->assignmentId=$assignment->id;

		$model->status=1;

		if($model->save()) {

			if(isset($_POST['InspectionData'])) {

			//Need to handle if relatedData NOT posted as only parent model will be saved and will not see validation errors.

				foreach ($_POST['InspectionData'] as $i=>$insData) {

					//Foreach Inspection saved, load inspectionData model

					//and assign form fields

					$InspectionData = new InspectionData;

					$InspectionData->inspectionId = $model->id;

					$InspectionData->criteriaName = $criteria[$i]; //Criteria is not coming from user input but from the query

					$InspectionData->compliant = $insData['compliant'];

					$InspectionData->notes = $insData['notes'];

					$InspectionData->save();

				}

			}

			//Set create flash message and send user to dashboard? page (change to Inspection History when built)

			Yii::app()->user->setFlash('create', 'Inspection recorded successfully.');

				$this->redirect(array('/dashboard'));

		}

	}



You should change your logic so that you’re doing something like:

(The kicker will be that you can’t validate for the ID of the Inspection on the children)




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

{

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

   $model->userId=Yii::App()->user->id;

   $model->assignmentId=$assignment->id;

   $model->status=1;

   if ( $model->validate() )

   {

      $foundInvalidChild = false;

      $arrInspectionData = array();

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

      {

          foreach ($_POST['InspectionData'] as $i=>$insData) {

             //Foreach Inspection saved, load inspectionData model

             //and assign form fields

             $InspectionData = new InspectionData;

             // massively assign the data posted

             $InspectionData->attributes = $insData;

             // we can only do this if the parent has been saved ... 

             if ( $model->id )

               $InspectionData->inspectionId = $model->id;

             $InspectionData->criteriaName = $criteria[$i]; //Criteria is not coming from user input but from the query


            // These should be massively assigned

            // $InspectionData->compliant = $insData['compliant'];

            // $InspectionData->notes = $insData['notes'];

            

             if ( ! $InspectionData->validate() )

                $foundInvalidChild = true;


             $arrInspectionData[] = $InspectionData;

         }


      }

      if ( !$foundInvalidChild && $model->save() ) 

      { 

           foreach( $arrInspectionData as $InspectionData )

           {

              $InspectionData->inspectionId = $model->id;

              $InspectionData->save();

           }

           // do the rest of your post-save stuff here.

      }

   }

   // do your draw form here

}



Brilliant!

I think your kicker comment will not be an issue because there is only one parent per form submitted. I have to think about this a little more - I’m not sure I entirely understand what you mean. The InspectionData table has an autoincrement primary ID and a FK to Inspection.

I had a similar situation in another area of my app using a many:many relationship but since I didn’t REQUIRE the children to be assigned it wasn’t an issue. Thanks for the help!!!

Just make sure that in your validation rules for the InspectionData that inspectionId isn’t required and you should be good to go, as far as that “kicker” goes ;)

Because, the model->id isn’t set until after it saves, so when you first loop, it would be null.

One more thing.

In my _form.php I’m using a CActiveForm with this line to display error summary:


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

In order to display the ‘child’ errors do I need to use AddError?

I shouldn’t work on code late in the today. Please disregard - I just need to use the same model that I am passing to my view. You’ll see I am using $data in one place and $InspectionData in another.

Cool…something I was looking for recently…

Thank you, after a long search, this finally solved my problem. <3 Dana