Validate fields from another model in form

Hi everyone, something in validation is bothering me badly, i want to know how to apply validation rules from one model in other, for example: i have 2 models, model A and model B, i have a form from model A which has fields from model B as well, but validation rules from model B are not applying in model’s A form, validations from model A works fine but the ones that come from model B aren’t working, i made the correct instances with the proper scenarios for the rules in the origin model’s controller but isn’t working, here’s the code of the validation rules that i’m using, the instances and the form, hope you can guide me and help me if i’m missing something thanks in advance:

validation rules()

Model Prestamo


array('cant_material, id_prestador, fecha_entrega', 'required', 'on'=>'prestamo', 'message'=>'Tiene que escoger {attribute} para proseguir con el prestamo!'),

Model Materiales


array('cota', 'required', 'on'=>'prestamos', 'message'=>'Debe introducir la cota del material para realizar la búsqueda!'),

Model Ejemplares


array('ejemplar', 'required', 'on'=>'prestar', 'message'=>'Escoja un ejemplar'),

Models instances with scenarios in PrestamoController


$model=new Prestamo('prestamo');

$modelEjemplar = new Ejemplares('prestar');

$materiales = new Materiales('prestamos');

Prestamo’s Form


<div id="materiales" class="container-fluid"><br>


        <div id="material_1" class="row-fluid" align="center">

            <fieldset class="mtrls"><!--Datos del Material1-->

                <legend class="span12 mtrs" style=" font-size: 17px;"><b>Datos del Material</b></legend>

                <div>

                    <div><?php echo $form->labelEx($materiales,'cota', array('for'=>'mat1')); ?></div>

                    <div>

                        <?php echo $form->textField($materiales,'cota',array('maxlength'=>'10', 'onchange'=>'buscarMaterial(1)', 'name'=>'materiales[]', 'id'=>'mat1')); ?>

                        <?php echo $form->error($materiales,'cota'); ?>

                    </div>

                    <div id="ejemplar1">

                        <?php echo $form->labelEx($ejemplares,'ejemplar'); ?>

                        <?php echo $form->dropDownList($ejemplares, 'ejemplar', CHtml::listData(Ejemplares::model()->findAll(array('order'=>'ejemplar asc')),'id', 'ejemplar'), array('name'=>'ejemplares[]', 'id'=>'ejemplar_1')); ?>

                        <?php echo $form->error($ejemplares,'ejemplar'); ?>

                    </div>

                <div id="mensajesSistema1"  class="materialData1"></div>

                <br>                    

                <div id="tabla-mat1" class="span12"></div>

                </div>

            </fieldset><!--fin datos del material1-->

        </div>

        <br>


        <div id="material_2" class="row-fluid" align="center">

            <fieldset class="mtrls"><!--Datos del Material2-->

                <legend class="span12 mtrs" style=" font-size: 17px;"><b>Datos del Material</b></legend>

                <div>

                    <div><?php echo $form->labelEx($materiales,'cota', array('for'=>'mat2')); ?></div>

                    <div>

                        <?php echo $form->textField($materiales,'cota',array('maxlength'=>'10', 'onchange'=>'buscarMaterial(2)', 'name'=>'materiales[]', 'id'=>'mat2')); ?>

                    </div>

                    <div id="ejemplar2">

                        <?php echo CHtml::label('Ejemplar(es)','ejemplar_2'); ?>

                        <?php echo $form->dropDownList($ejemplares, 'ejemplar', CHtml::listData(Ejemplares::model()->findAll(array('order'=>'ejemplar asc')),'id', 'ejemplar'), array('name'=>'ejemplares[]', 'id'=>'ejemplar_2')); ?>         

                    </div>

                <div id="mensajesSistema2"  class="materialData2"></div>

                <br>                    

                <div id="tabla-mat2" class="span12"></div>

                </div>

            </fieldset><!--fin datos del material2-->

        </div>

        <br>


        <div id="material_3" class="row-fluid" align="center">

            <fieldset class="mtrls"><!--Datos del Material3-->

                <legend class="span12 mtrs" style=" font-size: 17px;"><b>Datos del Material</b></legend>

                <div>

                    <div><?php echo $form->labelEx($materiales,'cota', array('for'=>'mat3')); ?></div>

                    <div>

                        <?php echo $form->textField($materiales,'cota',array('maxlength'=>'10', 'onchange'=>'buscarMaterial(3)', 'name'=>'materiales[]', 'id'=>'mat3')); ?>

                    </div>

                    <div id="ejemplar3">

                        <?php echo CHtml::label('Ejemplar(es)','ejemplar_3'); ?>

                        <?php echo $form->dropDownList($ejemplares, 'ejemplar', CHtml::listData(Ejemplares::model()->findAll(array('order'=>'ejemplar asc')),'id', 'ejemplar'), array('name'=>'ejemplares[]', 'id'=>'ejemplar_3')); ?>         

                    </div>

                <div id="mensajesSistema3"  class="materialData3"></div>

                <br>                    

                <div id="tabla-mat3" class="span12"></div>

                </div>

            </fieldset><!--fin datos del material3-->

        </div>

        <br>


        <div id="cant_materiales" class="row-fluid" align="center">

            <legend class="span12 mtrs" style=" font-size: 17px;"><b>Usuarios</b></legend>

            <div>

            <?php 

                $datos = Datos::model()->findAll('id_tipo=1 and borrado=FALSE');

                $data = array();


                foreach ($datos as $dato)

                    $data[$dato->id] = $dato->nombres . ' '. $dato->apellidos;

            ?>

            <?php echo $form->labelEx($model, 'id_prestador'); ?>

            <?php echo $form->dropDownList($model, 'id_prestador', $data, array('prompt'=>'Seleccione',

                                                                                'class'=>'input-medium')

                                            );

            ?>

            <?php echo $form->error($model,'id_prestador'); ?>

            </div>

            <div id="pass_error"></div>

            <div id="check-pass" class="input-append">

                <?php echo $form->passwordField($modelDatos, 'password'); ?>

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

                    'label'=>'Verificar',

                    'type'=>'primary',

                    'htmlOptions'=>array(

                        'id'=>'btn-pass',

                        'onclick'=>'verificarPass()',

                    ),

                )); ?>

            </div>

        </div>

        <br>


        <div id="tipo_prestamo" class="row-fluid" align="center">

            <legend class="span12 mtrs" style=" font-size: 17px;"><b>Tipo de Prestamo</b></legend>

            <div class="span5">

                <?php echo CHtml::label('Sala',CHtml::activeId($model, 'id_tipoprestamo')); ?>

                <?php echo CHtml::radioButton('tprestamo', true, array('value'=>1, 'uncheckvalue'=>null)); ?>

            </div>

            <div class="span5"> 

                <?php echo CHtml::label('Circulante',CHtml::activeId($model, 'id_tipoprestamo')); ?>

                <?php echo CHtml::radioButton('tprestamo', '', array('value'=>2, 'uncheckvalue'=>null)); ?>

            </div>

        </div>

        <br>


        <div id="fecha_prestamo" class="row-fluid" align="center">

            <legend class="span12 mtrs" style=" font-size: 17px;"><b>Fechas del Prestamo</b></legend>

                <div id="fecha_prestamo" class="span5">

                    <?php echo $form->textFieldRow($model,'fecha_prestamo', array('readonly'=>true, 'value'=>date("d-m-Y"),)); ?>

                </div>

                <div id="fecha_entrega" class="span6">

                    <?php echo $form->labelEx($model, 'fecha_entrega'); ?>

                    <?php $this->widget('zii.widgets.jui.CJuiDatePicker',

                                        array(

                                            'model' => $model,

                                            'attribute' => 'fecha_entrega',

                                            'value' => $model->fecha_entrega,

                                            'language' => 'es',

                                            'htmlOptions' => array('readonly' => "readonly", 'class' => 'input-large', 'id'=>'fentrega'),

                                            //additional javascript options for the date picker plugin

                                            'options' => array(

                                                            'autoSize' => true,

                                                            // 'defaultDate'=>$model->fechanacimiento,

                                                            //'dateFormat'=>'yy-m-d',

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

                                                            'buttonImage' => Yii::app()->baseUrl . '/images/calendario.png',

                                                            'buttonImageOnly' => true,

                                                            'buttonText' => 'Escoger fecha',

                                                            'selectOtherMonths' => true,

                                                            'showAnim' => 'slide',

                                                            'showButtonPanel' => true,

                                                            'showOn' => 'button',

                                                                    'changeMonth' => 'true',

                                                                    'changeYear' => 'true',

                                                                    'yearRange' => "1900:+nn",

                                                                    'minDate'=> 0,

                                                                ),

                                                            ));

                    ?>

                    <?php echo $form->error($model, 'fecha_entrega'); ?>

                </div>

        </div>

        <br><br>

        <div id="seccion-guardar" align="center">

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

                                array(

                                    'buttonType' => 'submit',

                                    'type' => 'info',

                                    'icon'=>'icon-ok icon-white',

                                    'label' => 'Guardar Prestamo',

                                    'htmlOptions' => array(

                                                        'id' => 'btn-guardar',

                                                    ),

                                )

                        );

            ?>

        </div>

    </div>

The thing here is that i’m not getting the validation errors coming from models Materiales and Ejemplares.

How to use a single form to collect data for two or more models

Thanks a lot, i knew that i was missing something from docs :D

Mr. tri while reviewed my code i just notice that the method explained in the link works only if you are working with massive assignment which in this case i can’t do it because in this form i used the same attribute from model Ejemplares in 3 different textFields due to my workflow so i made an array for the name attribute in the htmlOption of the element, that way i could obtain all the values that i was submitting, when i submit the form those textFields are submitted as an array without model meaning that can’t do massive assignment and can’t run validation rules over this data.

This is the way how i update records coming from this post


$operacion = Yii::app()->db->beginTransaction();


			try {


				$solicitante = Datos::model()->find('cedula=:cedula AND borrado=false AND id_tipo=2', array(':cedula'=>$_POST['Prestamo']['cedula']));


				echo "<pre>";print_r($_POST);echo"\n";print_r($solicitante);echo"\n";exit;


				if (!empty($solicitante)) {

					

					$model->id_solicitante = $solicitante->id;

					$model->id_status = 1;

					$model->id_tipoprestamo = $_POST['tprestamo'];

					

					//echo "<pre>";print_r($model);echo"\n";print_r($solicitante);echo"\n";print_r($_POST);exit;


					$validar = $model->validate();


					if ($validar) {

						

						if($model->save(false)){


							if (!empty($_POST['Materiales']) && !empty($_POST['ejemplares'])) {


								$materls = $_POST['Materiales'];

								$ejem = $_POST['ejemplares'];


								foreach ($materls as $key => $value) {


									if (!empty($value)) {

										

										$mat = Materiales::model()->find('cota=:cota AND borrado=false AND cantidad>0', array(':cota'=>$value));


										if (!empty($mat)) {

											

											$mat->cantidad = $mat->cantidad - 1;


											if ($mat->update()) {

												

												foreach ($ejem as $key => $valor) {

														

													if (!empty($valor)) {

															

														$ejmplr = Ejemplares::model()->find('id=:id AND borrado=false AND id_status=1', array(':id'=>$valor));


														if (!empty($ejmplr)) {

																

																$ejmplr->id_status = 2;


																$ejmplr->update();

														}

													}

												}											

											

											}else{


												throw new Exception("Error en actualización de datos", 6);

											}

										

										}else{


											throw new Exception("No quedan ejemplares disponible del material!", 5);

										}

									}

								}


								$operacion->commit();

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

							

							}else{


								throw new Exception("Error en envío de datos!", 4);

							}

						

						}else{


							throw new Exception("Ha ocurrido un error en el guardado de datos!", 3);

						}

					

					}else{


						throw new Exception("Error en la validación de datos!", 2);

					}

				

				}else{


					throw new Exception("Solicitante no encontrado!", 1);

					

				}

			

			} catch (Exception $e) {




				$operacion->rollback();

				Yii::app()->user->setFlash('error', $e->getMessage());

				$this->refresh();

			}

and this is what i obtain from post array

7238

post prestamos1.png