[EXTENSION] wForm

Hi,

I have been trying to implement a HAS_MANY relationship for a while now and just cant seem to get it to work properly, data will display perfectly but i am unable to save back to the DB.

I keep receiving the following error when trying to save.

Fatal error: Call to a member function relations() on a non-object in C:\Program Files (x86)\EasyPHP-5.3.9\www\mysite\protected\extensions\wform\WForm.php on line 284

What I am building is a bird identification db, the update page has all the information about a particular type of bird, along with key points (BirdNotes) and a multiple images of the bird (Photos), the Photos table also has a relation to another table for storing the image itself.

I have gone through and looked at the example included but I am unable to make it work. The same error will appears no matter which HAS_MANY relationship I put on the form.

All models are standard as generated using Giix

Any help would be appreciated.

Here is my Relations in the Model


public function behaviors() {

        return array(

            // attach wform behavior

            'wform' => array(

                'class' => 'ext.wform.WFormBehavior',

                // define relations which would be processed

                'relations' => array('idNativity0', 'idProtection0', 'idHabitat0', 'BirdNotes', 'Photos'),

            ),

        );

    }


public function relations() {

		return array(

			'idNativity0' => array(self::BELONGS_TO, 'Nativity', 'idNativity'),

			'idProtection0' => array(self::BELONGS_TO, 'Protection', 'idProtection'),

			'idHabitat0' => array(self::BELONGS_TO, 'Habitat', 'idHabitat'),

			'BirdNotes'=> array(self::HAS_MANY, 'BirdNote', 'idBird'),

			'Photos'=> array(self::HAS_MANY, 'Photo', 'idBird'),

		);

	}



Here is my Controller


	public function actionUpdate($id = null)

	{

		$model = $id ? Bird::model()->with('idNativity0', 'idProtection0', 'idHabitat0', 'BirdNotes', 'Photos')->findByPk($id) : new Bird();

		

		$model=$this->loadModel($id);


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

		{

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

			

			if($model->save()) {

				

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

			}

		}


		$this->render('update',array(

			'model'=>$model,

		));

	}

Here is the Form for the BirdNote portion


<div class="row clearfix hasManyRelation">

	<strong>Interesting Facts</strong>

		<!-- exists items -->

		<?php if ($model->BirdNotes): ?>

			<?php foreach ($model->BirdNotes as $index => $item): ?>

				<div class="has-many-item clearfix" style="background-color:#E4E4E4;padding:5px;margin-top:5px;">

					<div style="float:left;">

						<?php if (!$item->isNewRecord): ?>

							<?php echo $form->hiddenField($model, "BirdNotes.{$index}.idBirdNote"); ?>

						<?php endif; ?>

						<?php echo $form->labelEx($model, "BirdNotes.{$index}.Note"); ?>

						<?php echo $form->textField($model, "BirdNotes.{$index}.Note",array('size'=>50,'maxlength'=>255)); ?>

						<?php echo $form->error($model, "BirdNotes.{$index}.Note"); ?>

					</div>

					<div style="float:left;margin-left:10px;width:50px;text-align:center;">		

						<?php echo $form->labelEx($model, 'BirdNotes..Active'); ?>

						<?php echo $form->checkBox($model, 'BirdNotes..Active'); ?>

						<?php echo $form->error($model, 'BirdNotes..Active'); ?>

					</div>

					<div style="float:right;margin-left:10px;">

						<a href="#" class="delete">Delete</a>

					</div>

				</div>

			<?php endforeach ?>

		<?php endif; ?>

	 

		<!-- create new items -->

		<div style="display:none;" class="has-many-item just-empty-form-template-hasManyRelation">

			<div class="clearfix" style="background-color:#E4E4E4;padding:5px;margin-top:5px;">

				<div style="float:left;">

					<?php echo $form->labelEx($model, 'BirdNotes..Note'); ?>

					<?php echo $form->textField($model, 'BirdNotes..Note'); ?>

					<?php echo $form->error($model, 'BirdNotes..Note'); ?>

								

					<?php echo $form->labelEx($model, 'BirdNotes..Active'); ?>

					<?php echo $form->checkBox($model, 'BirdNotes..Active'); ?>

					<?php echo $form->error($model, 'BirdNotes..Active'); ?>

					<br />

					<a href="#" class="delete">Cancel</a>

				</div>

			</div>

		</div>

	 

		<a href="#" class="add">Add Note</a>

	</div>



--------- SOLVED ----------

Managed to locate the problem, for some reason the installation of PHP I have was not replacing the index variable in the string "BirdNotes.{$index}.Note" and putting in the index, neither that or "BirdNotes.$index.Note" worked, once I changed it to "BirdNotes." . $index . ".Note" everything came right.

I also added the following to line 284 of wForm.php, this will fix the array so that a CException is thrown for the invalid relation name, in my case it was throwing {index}




if (empty($model->relations)) { $model = array_shift(array_values($model)); }



Well I am getting a new error now, code is still as per above.

All appears to be working as it should. I can add multiple related rows and delete most of them.

The problem is I am unable to delete ALL rows in a HAS_MANY relation, it simply will not delete the last row.

If I delete all and save then no rows will be deleted.

If I delete all apart from the last row then they will delete, but I will then be unable to delete the remaining row.

I am guessing this is to do with the post data not containing any results so it simply ignores it instead of deleting any remaining rows, I am not sure how to solve this so some help would be appreciated.

Thanks in advance.

---------- SOLVED ----------

I posted to soon, the problem was when the data is posted back there is no data for the removed relation.

To test this I simply added the following lines to my controller after testing for the appropriate $_POST




if (!isset($_POST['Bird']['BirdNotes'])) {

	$_POST['Bird']['BirdNotes'] = array();

}



This will put an empty array in place if there is no data posted back for the relation causing wForm to process it as a deletion.

So the controller is now




public function actionUpdate($id = null)

        {

                $model = $id ? Bird::model()->with('idNativity0', 'idProtection0', 'idHabitat0', 'BirdNotes', 'Photos')->findByPk($id) : new Bird();

                

                $model=$this->loadModel($id);


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

                {

                        if (!isset($_POST['Bird']['BirdNotes'])) {

                        	$_POST['Bird']['BirdNotes'] = array();

                        }

                        if (!isset($_POST['Bird']['Photos'])) {

                        	$_POST['Bird']['Photos'] = array();

                        }

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

                        

                        if($model->save()) {

                                

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

                        }

                }


                $this->render('update',array(

                        'model'=>$model,

                ));

        }



thanks an0nz, i have same problem and i was solved it :)

i am not getting validation errors in sub related form, instead i am getting only the error which says about related model is invalid,

is i am missing somthing.

what this should return

$product->getErrors();

@devnegikec:

Were you able to solve this? I also want to add more fields to Product_2_tag table such as SortOrder. I am stuck. Please help…

what replacement wform for yii2 ?