Formulario para multiples modelos relacionados

Buenas tardes, es algo comun que necesitemos hacer formularios de multiples modelos, ya lo hice pero mi problema es que cuando le doy a guardar, en la base de datos duplica los registros, graba hasta 3 veces el mismo registro en ambas tablas de ambos modelos y la verdad no se porque está pasando eso.

MER




 _______________________________                                           ____________________

|_____tbl_maximaautoridad_______|<-$b                                     |___tbl_estructura___|

|                               |                                         | id                 |   

|  id                           |                                         | denominacion       |

|  idpersona integer            |    _______________________________      |_ect________________|

|  idcargo                      |   |_tbl_maximaautoridadestructura_|<-$a               |

|  nroresoluciongaceta integer  |   | id                            |                   |

|  nrogacetaoficial             |   | idestructura                  |<-------------------

|  fechagaceta                  |-->| idmaximaautoridad             |

|  fecharesolucion              |   |_______________________________|

|  fechainicio                  |

|  fechafin                     |

|  correoelectronico            |

|  telefonooficina              |

|__estatusreg___________________| 




El form que estoy haciendo corresponde a una combinacion de tbl_maximaautoridadestructura que llamo $a y tbl_maximaautoridad que llamo $b, tambien aclaro que todo lo hago desde el model TblMaximaautoridadEstructura y aqui es donde trato de incluir el TblMaximaautoridad

aqui lo que tengo…

Mi form




<script type="text/javascript">


function soloNumeros(e){

	valor = e.which;

	//alert(valor);

	if( (valor >= 48 && valor <= 57) || valor==8 )

		return true;

	else

		return false;	

}





</script>


<div class="form">


<?php 

	$form = $this->beginWidget('CActiveForm', array( 'id'=>'user-form','enableAjaxValidation'=>true, ));

	

	if ($a->isNewRecord==false) {		


		$b=TblMaximaautoridad::model()->findByPk($a->idmaximaautoridad); 

		

	} else {


		echo $form->errorSummary(array($a,$<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/cool.gif' class='bbc_emoticon' alt='B)' />); 

	

	}

?>

<p class="note">Los campos señalados con <span class="required">*</span> son requeridos.</p>


<!-- $A ********************************************************************************************************************** -->

<!-- $A ********************************************************************************************************************** -->

<!-- $A ********************************************************************************************************************** -->


	<div class="row">

		<?php echo $form->labelEx($a,'idestructura'); ?>

		

		<!-- COMBO SELECCION DE MAXIMAS AUTORIDADES NO RELACIONADAS CON ORGANISMO / ENTE TOMADAS POR EL IDPERSONA.CEDULA-->

		<?php echo $form->dropDownList($a,'idestructura',

		CHtml::listData(TblEstructura::model()->findAll(

			array(

					//"condition"=>"t.id NOT IN (SELECT idestructura FROM tbl_maximaautoridad_estructura) OR t.id = ".$model->idestructura."0 ",

					"condition"=>"t.id NOT IN (SELECT idestructura FROM tbl_maximaautoridad_estructura) OR t.id = " .($a->isNewRecord ? '0' : $a->idestructura),

					// Esta condicion no permite mostrar en el select los Organos / Entes que ya tengan una Maxima Autoridad asignada.

				)

			),'id','denominacion'),

			array(

				'prompt' => 'Seleccione un Organismo o Ente...','style'=>"width:70%"

				)

		); ?>

		<?php echo $form->error($a,'idestructura'); ?>

	</div>


<!-- $B ********************************************************************************************************************** -->

<!-- $B ********************************************************************************************************************** -->

<!-- $B ********************************************************************************************************************** -->

	

	<div class="row">

		<?php echo $form->labelEx($b,'Busque una persona');?>


		<?php echo CHtml::activeTextField($b,'buscarcedula',

				array('value'=> ($b->isNewRecord ? '' : $b->idpersona0->cedula),

						'id'=>'cedula','style'=>"width:12%",'onkeypress'=>'return soloNumeros(event, this)', 'placeholder'=>'Indroduzca Cédula',

                'ajax'=>array(

                    'type'=>'POST',

                    'url'=>CController::createUrl('TblPersona/buscarnombrecompletoMA'),

                    'update'=>'#nombrediv'

                )

               ));?>

             

		<div id="nombrediv">

		<?php echo $form->textField($b,'idpersona',array('style'=>'display:none')); ?>

		<?php echo $form->textField($b,'datos',array('value'=>($b->isNewRecord ? '' : $b->idpersona0->nombre.' '.$b->idpersona0->apellido), 'style'=>'width:50%', 'readonly'=>true, 'placeholder'=>'Información personal')); ?>

		</div> 

	</div>

	

<!-- ************************************************************************************************************************* -->		

	

	<div class="row">

		<?php echo $form->labelEx($b,'Tipo de Cargo'); ?>

		<?php echo $form->dropDownList($b,'idcargo',

			CHtml::listData(TblCargo::model()->findAll(),'id','denominacion')); ?>

		<?php echo $form->error($b,'idcargo'); ?>

	</div>	


	<div class="row">

		<?php echo $form->labelEx($b,'N° de Resolución de Gaceta Oficial'); ?>

		<?php echo $form->textField($b,'nroresoluciongaceta'); ?>

		<?php echo $form->error($b,'nroresoluciongaceta'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($b,'N° de Gaceta Oficial'); ?>

		<?php echo $form->textField($b,'nrogacetaoficial'); ?>

		<?php echo $form->error($b,'nrogacetaoficial'); ?>

	</div>




<!-- ********************************* FECHAS ********************************* -->


	<div class="row">

		<?php echo $form->labelEx($b,'Fecha de Emisión de la Gaceta Oficial'); ?>

		<?php 

		$this->widget("zii.widgets.jui.CJuiDatePicker",array(

			"attribute"=>"fechagaceta",

			"model"=>$b,

			"language"=>"es",

			"options"=>array(

					"dateFormat"=>"yy-mm-dd",

					"showButtonPanel"=> true,

					"changeYear"=>true

				)

			));

		?>

		<?php echo $form->error($b,'fechagaceta'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($b,'Fecha de Resolución de la Gaceta Oficial'); ?>

		<?php 

		$this->widget("zii.widgets.jui.CJuiDatePicker",array(

			"attribute"=>"fecharesolucion",

			"model"=>$b,

			"language"=>"es",

			"options"=>array(

					"dateFormat"=>"yy-mm-dd",

					"changeYear"=>true,

					"showButtonPanel"=> true

				)

			));

		?>

		<?php echo $form->error($b,'fecharesolucion'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($b,'Fecha Inicio como Maxima Autoridad'); ?>

		<?php 

		$this->widget("zii.widgets.jui.CJuiDatePicker",array(

			"attribute"=>"fechainicio",

			"model"=>$b,

			"language"=>"es",

			"options"=>array(

					"dateFormat"=>"yy-mm-dd",

					"showButtonPanel"=> true,

					"changeYear"=>true

				)

			));

		?>

		<?php echo $form->error($b,'fechainicio'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($b,'Fecha Fin como Maxima Autoridad'); ?>

		<?php 

		$this->widget("zii.widgets.jui.CJuiDatePicker",array(

			"attribute"=>"fechafin",

			"model"=>$b,

			"language"=>"es",

			"options"=>array(

					"dateFormat"=>"yy-mm-dd",

					"showButtonPanel"=> true,

					"changeYear"=>true

				)

			));

		?>

		<?php echo $form->error($b,'fechafin'); ?>

	</div>


<!-- ********************************* FECHAS ********************************* -->


	<div class="row">

		<?php echo $form->labelEx($b,'Correo Electronico'); ?>

		<?php echo $form->textField($b,'correoelectronico'); ?>

		<?php echo $form->error($b,'correoelectronico'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($b,'Telefono de oficina'); ?>

		<?php echo $form->textField($b,'telefonooficina'); ?>

		<?php echo $form->error($b,'telefonooficina'); ?>

	</div>


	<div class="row" style="display:none">

		<?php echo $form->labelEx($b,'estatusreg'); ?>

		<?php echo $form->textField($b,'estatusreg',array('readonly'=>true)); ?>

		<?php echo $form->error($b,'estatusreg'); ?>

	</div>

	

<!-- ********************************************************************************************************************** -->

<!-- ********************************************************************************************************************** -->

<!-- ********************************************************************************************************************** -->


	<div class="row buttons">

	<?php echo CHtml::submitButton($a->isNewRecord ? 'Crear' : 'Actualizar'); ?>

	</div> 

	

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


</div>



Mi Controller




public function actionCreate()

	{

		$a = new TblMaximaautoridadEstructura;

		$b = new TblMaximaautoridad;

		

		$this->performAjaxValidation(array($a,$<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/cool.gif' class='bbc_emoticon' alt='B)' />);

		if(isset($_POST['TblMaximaautoridadEstructura'],$_POST['TblMaximaautoridad']))

		{

			$a->attributes=$_POST['TblMaximaautoridadEstructura'];

			$b->attributes=$_POST['TblMaximaautoridad'];

			

			$sql='select max(id) from tbl_maximaautoridad;';

			

			$connection=Yii::app()->db;

			$command=$connection->createCommand($sql);

			

			$row=$command->queryRow();

			$row["max"]++;

			$b->id=$row["max"];

			$a->idmaximaautoridad=$row["max"];

			

			if($b->save() && $a->save())

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

		}

		$this->render('create',array('b'=>$b,'a'=>$a));

	}



mi vista Create




<?php echo $this->renderPartial('_form', array('a'=>$a, 'b'=>$<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/cool.gif' class='bbc_emoticon' alt='B)' />); ?>



Ya no se que mas ver, algo esta pasando y me esta guardando 3 veces en la base de datos cuando le doy a guardar. lo demas funciona perfecto T_T pls halp! :)

Perdonen el desorden, intenté poner todo lo necesario. xD

Cuando utilizas la validación del formulario por ajax, cada vez que cambias el valor de un input se envia un POST por medio de ajax, y en tu controller cuando hay un POST guardas los datos, entonces cada vez que modificas algo del formulario se guarda en la base de datos. Lo que tienes que hacer es validar que solo se guarden los datos cuando el POST sea sin ajax.


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

    //Tu codigo Aqui para guardar los datos

}

Excelente a18327 muchisimas gracias. tengo que ponerme a investigar sobre lo que me dijiste y hacer ejercicios porque no lo entendi muy bien. +1 a tu respuesta y de nuevo muchisimas gracias, aca dejo el actionCreate como quedó por si alguien lo necesita :) feliz dia.




public function actionCreate()

	{

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

			//Tu codigo Aqui para guardar los datos

		

		$a = new TblMaximaautoridadEstructura;

		$b = new TblMaximaautoridad;

		

		$this->performAjaxValidation(array($a,$<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/cool.gif' class='bbc_emoticon' alt='B)' />);

		if(isset($_POST['TblMaximaautoridadEstructura'],$_POST['TblMaximaautoridad']))

		{

			$a->attributes=$_POST['TblMaximaautoridadEstructura'];

			$b->attributes=$_POST['TblMaximaautoridad'];

			

			$sql='select max(id) from tbl_maximaautoridad;';

			

			$connection=Yii::app()->db;

			$command=$connection->createCommand($sql);

			

			$row=$command->queryRow();

			$row["max"]++;

			$b->id=$row["max"];

			$a->idmaximaautoridad=$row["max"];

			

			if($b->save() && $a->save())

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

		}

		$this->render('create',array('b'=>$b,'a'=>$a));

		

		}

	}



Deberia ser asi


public function actionCreate()

	{

		$a = new TblMaximaautoridadEstructura;

		$b = new TblMaximaautoridad;


		if(isset($_POST['TblMaximaautoridadEstructura'],$_POST['TblMaximaautoridad']))

		{

			$a->attributes=$_POST['TblMaximaautoridadEstructura'];

			$b->attributes=$_POST['TblMaximaautoridad'];


			//La validación por ajax se hace despues de haber pasado los datos del post a los modelos

			$this->performAjaxValidation(array($a,$<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/cool.gif' class='bbc_emoticon' alt='B)' />);


			if (!isset ( $_POST ['ajax'] )) {//Solo guarda los datos cuando el POST no es por ajax

				//Tu codigo Aqui para guardar los datos

				$sql='select max(id) from tbl_maximaautoridad;';


				$connection=Yii::app()->db;

				$command=$connection->createCommand($sql);


				$row=$command->queryRow();

				$row["max"]++;

				$b->id=$row["max"];

				$a->idmaximaautoridad=$row["max"];


				if($b->save() && $a->save())

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

			}

		}

		$this->render('create',array('b'=>$b,'a'=>$a));


	}

Excelente muchas gracias, disculpa a18327 ahora que me doy cuenta tengo un problema con el actionUpdate, me dice que la sentencia sql falla. este es mi actionUpdate




public function actionUpdate($id)

	{

			

			$a=new TblMaximaautoridadEstructura;

			$b=new TblMaximaautoridad;

			

			$this->performAjaxValidation(array($a,$<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/cool.gif' class='bbc_emoticon' alt='B)' />);

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

			

			if(isset($_POST['TblMaximaautoridadEstructura'],$_POST['TblMaximaautoridad']))

			{

				

				$a->attributes=$_POST['TblMaximaautoridadEstructura'];

				$b->attributes=$_POST['TblMaximaautoridad'];

		

				$b->id=$a->idmaximaautoridad;

			

			$b->setIsNewRecord(false);

			if($a->save() && $b->update())

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

			

			}

			

			$this->render('update',array('a'=>$a,'b'=>$<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/cool.gif' class='bbc_emoticon' alt='B)' />);

		

	}



este el error que me manda, no se si es error de formato de fecha o es otra cosa porque yo he usado esos formatos par fecha en otros modelos sin problemas, combinando los modelos me salta ese error. ademas tambien me señala aca ayuda pls :(




$b->attributes=$_POST['TblMaximaautoridad'];

157         

158                 $b->id=$a->idmaximaautoridad;

159             

160             $b->setIsNewRecord(false);

161             if($a->save() && $b->update())

162                 $this->redirect(array('view','id'=>$a->id));

163             

164             }

165             

166             $this->render('update',array('a'=>$a,'b'=>$<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/cool.gif' class='bbc_emoticon' alt='B)' />);




CDbCommand falló al ejecutar la sentencia SQL: SQLSTATE[22007]: Invalid datetime format: 7 ERROR: la sintaxis de entrada no es válida para tipo date: «». The SQL statement executed was: UPDATE "tbl_maximaautoridad" SET "estatusreg"=:yp0, "descripcion"=:yp1, "idpersona"=:yp2, "idcargo"=:yp3, "nroresoluciongaceta"=:yp4, "fecharesolucion"=:yp5, "nrogacetaoficial"=:yp6, "fechagaceta"=:yp7, "fechainicio"=:yp8, "fechafin"=:yp9, "correoelectronico"=:yp10, "telefonooficina"=:yp11, "id"=:yp12 WHERE "tbl_maximaautoridad"."id"=6 

Probablemente sea un problema con los campos vacios, se tienen que setear a null antes de guardar, para ello debes poner lo siguiente, en los rules del model.


class Modelo extends CActiveRecord {

    ...

    ...

    public function rules() {		

        return array (

               ...

               ...

               array(

                   'fechagaceta,fecharesolucion,fechainicio,fechafin', 

                   'default', 

                   'setOnEmpty' => true, 

                   'value' => null

               ),

        );

    } 

    ...

    ...

}

consegui como hacerlo, solo tenia que hacerun beforesave en el modelo tbl_maximaautoridad =)




protected function beforeSave()

	{

		if ($this->fechafin == ''){

	

			$this->setAttribute('fechafin', null);

		}

	

		return parent::beforeSave();

	}