Duplicate Insertion Of A Record

Hi everyone, I’m experiencing some weird issues with a simple record insertion which gets to be saved twice instead of a single time. This is the form where the user should insert his datas:


   <?php

   	$action=$this->createUrl('valutazioneRischio/new?controller='.$this->getId().'&idmodel='.$idmodel);

	$tableName=$this->loadModel($idmodel)->tableName();

    $form = $this->beginWidget('ext.AweCrud.components.AweActiveForm', array(

    'id' => 'valutazioneRischio-form',

    'enableAjaxValidation' => false,

    'enableClientValidation'=> false,

	'action'=> $action,

    ));

	?>




   <p class="note">

        <?php echo Yii::t('AweCrud.app', 'Fields with') ?> <span class="required">*</span>

        <?php echo Yii::t('AweCrud.app', 'are required') ?>.    </p>


    <?php echo $form->errorSummary($model) ?>


                                        <?php echo $form->dropDownListRow($model, 'unita_produttiva_id', CHtml::listData(UnitaProduttiva::model()->findAll(), 'id', UnitaProduttiva::representingColumn()), array('prompt' => Yii::t('AweApp', 'None'))) ?>

                                        <?php echo $form->dropDownListRow($model, 'pericolo_id', CHtml::listData(Pericolo::model()->findAll(), 'id', Pericolo::representingColumn()), array('prompt' => Yii::t('AweApp', 'None'))) ?>

                                        <?php echo $form->textFieldRow($model, 'descrizione', array('class' => 'span5')) ?>

                                        <?php echo $form->textFieldRow($model, 'esposizione', array('class' => 'span5')) ?>

                                        <?php echo $form->textFieldRow($model, 'limiti', array('class' => 'span5')) ?>

                                        <?php echo $form->textFieldRow($model, 'probabilita', array('class' => 'span5')) ?>

                                        <?php echo $form->textFieldRow($model, 'danno', array('class' => 'span5')) ?>

                                        <?php echo $form->textFieldRow($model, 'stima', array('class' => 'span5')) ?>

                                        <?php echo $form->textFieldRow($model, 'probabilita_residua', array('class' => 'span5')) ?>

                                        <?php echo $form->textFieldRow($model, 'danno_residuo', array('class' => 'span5')) ?>

                                        <?php echo $form->textFieldRow($model, 'stima_residua', array('class' => 'span5')) ?>

                                        <?php echo $form->textFieldRow($model, 'note_residuo', array('class' => 'span5')) ?>

			        					<?php echo $form->hiddenField($model, 'riferimento', array('class' => 'span5','value'=> $tableName)) ?>

			        					<?php echo $form->hiddenField($model, 'campo', array('class' => 'span5','value'=> $idmodel)) ?>


			        			        			

    <div class="form-actions">

                <?php $this->widget('bootstrap.widgets.TbButton', array(

			'buttonType'=>'submit',

			'type'=>'primary',

			'label'=>$model->isNewRecord ? Yii::t('AweCrud.app', 'Create') : Yii::t('AweCrud.app', 'Save'),

		)); ?>

        <?php $this->widget('bootstrap.widgets.TbButton', array(

			'label'=> Yii::t('AweCrud.app', 'Cancel'),

			'htmlOptions' => array('onclick' => '$("#valutazioneRischio-form").parents(".collapse").collapse("hide")')

		)); ?>

    </div>


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

</div>

The method in the controller is the following:


		public function actionNew($controller=null,$idmodel=null)

	{	

		$model = new ValutazioneRischio;	

        $this->performAjaxValidation($model, 'ValutazioneRischio-form');

		$redirect=$this->createUrl($controller."/".$idmodel);

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

		{	

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

			if($model->save()) {				

				$this->redirect($redirect);

            }

			else{

				$this->render('application.views.site.paginaErrore', array('model' => $model,

				));

			}

		}

	}

And this is the base model


<?php


/**

 * This is the model base class for the table "valutazione_rischio".

 * DO NOT MODIFY THIS FILE! It is automatically generated by AweCrud.

 * If any changes are necessary, you must set or override the required

 * property or method in class "ValutazioneRischio".

 *

 * Columns in table "valutazione_rischio" available as properties of the model,

 * followed by relations of table "valutazione_rischio" available as properties of the model.

 *

 * @property integer $id

 * @property integer $unita_produttiva_id

 * @property integer $pericolo_id

 * @property string $riferimento

 * @property string $campo

 * @property string $descrizione

 * @property integer $esposizione

 * @property string $limiti

 * @property integer $probabilita

 * @property integer $danno

 * @property integer $stima

 * @property integer $probabilita_residua

 * @property integer $danno_residuo

 * @property integer $stima_residua

 * @property string $note_residuo

 * @property string $data_modifica

 * @property string $utente_modifica

 *

 * @property MisuraTecnica[] $misuraTecnicas

 * @property MisuraAmministrativa[] $misuraAmministrativas

 * @property Pericolo $pericolo

 * @property UnitaProduttiva $unitaProduttiva

 * @property Giudizio[] $giudizios

 * @property Dpi[] $dpis

 * @property ProtocolloSanitario[] $protocolloSanitarios

 */

abstract class BaseValutazioneRischio extends AweActiveRecord {


    public static function model($className=__CLASS__) {

        return parent::model($className);

    }


    public function tableName() {

        return 'valutazione_rischio';

    }


    public static function representingColumn() {

        return 'descrizione';

    }


    public function rules() {

        return array(

            array('unita_produttiva_id, pericolo_id, esposizione, probabilita, danno, stima, probabilita_residua, danno_residuo, stima_residua', 'numerical', 'integerOnly'=>true),

            array('riferimento, campo, descrizione, limiti, note_residuo, data_modifica, utente_modifica', 'safe'),

            array('unita_produttiva_id, pericolo_id, riferimento, campo, descrizione, esposizione, limiti, probabilita, danno, stima, probabilita_residua, danno_residuo, stima_residua, note_residuo, data_modifica, utente_modifica', 'default', 'setOnEmpty' => true, 'value' => null),

            array('id, unita_produttiva_id, pericolo_id, riferimento, campo, descrizione, esposizione, limiti, probabilita, danno, stima, probabilita_residua, danno_residuo, stima_residua, note_residuo, data_modifica, utente_modifica', 'safe', 'on'=>'search'),

        );

    }


    public function relations() {

        return array(

            'misuraTecnicas' => array(self::HAS_MANY, 'MisuraTecnica', 'valutazione_rischio_id'),

            'misuraAmministrativas' => array(self::HAS_MANY, 'MisuraAmministrativa', 'valutazione_rischio_id'),

            'pericolo' => array(self::BELONGS_TO, 'Pericolo', 'pericolo_id'),

            'unitaProduttiva' => array(self::BELONGS_TO, 'UnitaProduttiva', 'unita_produttiva_id'),

            'giudizios' => array(self::HAS_MANY, 'Giudizio', 'valutazione_rischio_id'),

            'dpis' => array(self::MANY_MANY, 'Dpi', 'valutazione_rischio_has_dpi(valutazione_rischio_id, dpi_id)'),

            'protocolloSanitarios' => array(self::MANY_MANY, 'ProtocolloSanitario', 'valutazione_rischio_has_protocollo_sanitario(valutazione_rischio_id, protocollo_sanitario_id)'),

        );

    }


    /**

     * @return array customized attribute labels (name=>label)

     */

    public function attributeLabels() {

        return array(

                'id' => Yii::t('app', 'ID'),

                'unita_produttiva_id' => Yii::t('app', 'Unita Produttiva'),

                'pericolo_id' => Yii::t('app', 'Pericolo'),

                'riferimento' => Yii::t('app', 'Riferimento'),

                'campo' => Yii::t('app', 'Campo'),

                'descrizione' => Yii::t('app', 'Descrizione'),

                'esposizione' => Yii::t('app', 'Esposizione'),

                'limiti' => Yii::t('app', 'Limiti'),

                'probabilita' => Yii::t('app', 'Probabilita'),

                'danno' => Yii::t('app', 'Danno'),

                'stima' => Yii::t('app', 'Stima'),

                'probabilita_residua' => Yii::t('app', 'Probabilita Residua'),

                'danno_residuo' => Yii::t('app', 'Danno Residuo'),

                'stima_residua' => Yii::t('app', 'Stima Residua'),

                'note_residuo' => Yii::t('app', 'Note Residuo'),

                'data_modifica' => Yii::t('app', 'Data Modifica'),

                'utente_modifica' => Yii::t('app', 'Utente Modifica'),

                'misuraTecnicas' => null,

                'misuraAmministrativas' => null,

                'pericolo' => null,

                'unitaProduttiva' => null,

                'giudizios' => null,

                'dpis' => null,

                'protocolloSanitarios' => null,

        );

    }


    public function search() {

        $criteria = new CDbCriteria;


        $criteria->compare('id', $this->id);

        $criteria->compare('unita_produttiva_id', $this->unita_produttiva_id);

        $criteria->compare('pericolo_id', $this->pericolo_id);

        $criteria->compare('riferimento', $this->riferimento, true);

        $criteria->compare('campo', $this->campo, true);

        $criteria->compare('descrizione', $this->descrizione, true);

        $criteria->compare('esposizione', $this->esposizione);

        $criteria->compare('limiti', $this->limiti, true);

        $criteria->compare('probabilita', $this->probabilita);

        $criteria->compare('danno', $this->danno);

        $criteria->compare('stima', $this->stima);

        $criteria->compare('probabilita_residua', $this->probabilita_residua);

        $criteria->compare('danno_residuo', $this->danno_residuo);

        $criteria->compare('stima_residua', $this->stima_residua);

        $criteria->compare('note_residuo', $this->note_residuo, true);

        $criteria->compare('data_modifica', $this->data_modifica, true);

        $criteria->compare('utente_modifica', $this->utente_modifica, true);


        return new CActiveDataProvider($this, array(

            'criteria' => $criteria,

        ));

    }


    public function behaviors() {

        return array_merge(array(

        ), parent::behaviors());

    }

	

	//funzione after find usata dopo aver letto i dati da db, viene usata per convertire le date in formato italiano

	public function afterFind(){

		parent::afterFind();

		

		//Template per cambiare formato di eventuali campi dati (Tipo DATE)

		//$this-> NOME CAPO DATO DA CAMBIARE =Yii::app()->dateFormatter->format('dd/MM/yyyy',$this-> NOME CAPO DATO DA CAMBIARE );     

		

		$this->data_modifica=Yii::app()->dateFormatter->formatDateTime(   

					CDateTimeParser::parse(

							$this->data_modifica, 

							'yyyy-MM-dd hh:mm:ss'

						),

                    'full','short');

	}


	//Impostazione data ultima modifica e nome user che l'ha eseguita. 

	public function beforeSave(){

	

		//Template per cambiare formato di eventuali campi dati (Tipo DATE)

		//$this-> NOME CAPO DATO DA CAMBIARE =Yii::app()->dateFormatter->format('yyyy/MM/dd',$this-> NOME CAPO DATO DA CAMBIARE );     


		$this->data_modifica= new CDbExpression('NOW()');

		$this->utente_modifica= Yii::app()->user->name;

		

		//QUESTE RIGHE SERVONO SE LA FORM PREVEDE UPLOAD IL PATH DEVE ESSERE CAMBIATO IN ACCORDO CON IL PATH USATO

		//if($this->isNewRecord){

		//	$this->path=Yii::app()->getBasePath().'/data/documenti/'.$this->path;

		//}

		

		return parent::beforeSave();

	}

	

	//template della funzione che serve per eliminare eventuali file di cui si è effettuato l'upload precedentemente

	//public function afterDelete(){

	//

	//	Usare la seguente riga di codice per ogni path $this->"path" dove "path" è il nome del campo dato contenente il path

	//   unlink($this->path);

	//	return parent::afterDelete();

	//}

	

}

What’s strange is I do have verified that commenting in the controller


$this->performAjaxValidation($model, 'ValutazioneRischio-form');



fixes the problem. However I lose the real time validation (of course), it’s not giving the same issues in similar forms and I don’t get why it should cause a database malfunction. Anyone has a clue on how to explain this? I’ll provide additional code if needed, just point me out what you need to see :) thanks in advance!

EDIT: I forgot: in the view code, "enableAjaxValidation" was set to true. Had to set it to false to "fix" the problem along with the line commenting I told above.

Try this:


$this->performAjaxValidation($model);

in place of


$this->performAjaxValidation($model, 'ValutazioneRischio-form');



Add one more function to perform validation.


protected function performAjaxValidation($model)

{

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

	{

		echo CActiveForm::validate($model);

		Yii::app()->end();

	}

}

That did it! I re-enabled validation in the controller as you suggested:


		public function actionNew($controller=null,$idmodel=null)

	{	

		$model = new ValutazioneRischio;	

        $this->performAjaxValidation($model);

		$redirect=$this->createUrl($controller."/".$idmodel);

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

		{	

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

			if($model->save()) {				

				$this->redirect($redirect);

            }

			else{

				$this->render('application.views.site.paginaErrore', array('model' => $model,

				));

			}

		}

	}

}

and in my view I set back


    $form = $this->beginWidget('ext.AweCrud.components.AweActiveForm', array(

    'id' => 'valutazioneRischio-form',

    'enableAjaxValidation' => true,

    'enableClientValidation'=> false,

	'action'=> $action,

    ));

The last edit I did to match your performAjaxValidation function was removing a condition in my former code, which was:


	protected function performAjaxValidation($model, $form=null)

	{

		if(isset($_POST['ajax']) && $_POST['ajax'] === 'valutazione-rischio-form')

		{

			echo CActiveForm::validate($model);

			Yii::app()->end();

		}

	}

and set it to


	protected function performAjaxValidation($model, $form=null)

	{

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

		{

			echo CActiveForm::validate($model);

			Yii::app()->end();

		}

	}

Now it works perfectly. Huge thanks for that! Out of curiosity: why did ajax validation cause an extra row to be recorded in my db? Isn’t the data type checked through model files? Thanks again for your help and quickness :)


'id' => 'valutazioneRischio-form',


$this->performAjaxValidation($model, 'ValutazioneRischio-form');

The difference is the capital V. Comparing strings in PHP is case sensitive, so your AJAX validation was ignored altogether, causing it to continue with saving the model.

Thanks a lot for the explanation :)