Form In Relazione Con Piu Modelli

Buongiorno a tutti,

qualcuno potrebbe cortesemente spiegarmi come lavorare su un form che gestisce diversi model che usano tipologie classe differenti (ovvero CActiveRecords e CFormModel)?

in pratica…

io ho un controller che gestisce il form sul quale vengono istanziati i 3 models:




<?php


class BookingController extends Controller

{

	/**

	 * @var string the default layout for the views. Defaults to '//layouts/column2', meaning

	 * using two-column layout. See 'protected/views/layouts/column2.php'.

	 */

	public $layout='//layouts/column2';

        public $defaultAction = 'new';

	/**

	 * @return array action filters

	 */

	public function filters()

	{

		return array(

			'accessControl', // perform access control for CRUD operations

			'postOnly + delete', // we only allow deletion via POST request

		);

	}


	public function accessRules()

	{

		return array(

			array('allow',  // allow all users to perform 'index' and 'view' actions

				'actions'=>array('index', 'new', 'view','SelectTpb','SelectCompagnia'),

				'users'=>array('*'),

			),

			array('allow', // allow authenticated user to perform 'create' and 'update' actions

				'actions'=>array('update'),

				'users'=>array('@'),

			),

			array('allow', // allow admin user to perform 'admin' and 'delete' actions

				'actions'=>array('admin','delete'),

				'users'=>array('admin'),

			),

			array('deny',  // deny all users

				'users'=>array('*'),

			),

		);

	}

public function actionNew()

{

    $modelA=new Dati;

    $modelB=new Tratte;

    $modelC=new Compagnie;

 

    $this->performAjaxValidation(array($modelA,$modelB,$modelC));

    if(isset($_POST['Tratte'],$_POST['Compagnie'],$_POST['Dati']))

    {

        // populate input data to $a and $b

        $modelA->attributes=$_POST['Dati'];

        $modelB->attributes=$_POST['Tratte'];

        $modelC->attributes=$_POST['Compagnie'];

        

 

        // validate BOTH $modelA, $modelB and $modelC

        $valid=$modelA->validate();

        $valid=$modelB->validate() && $valid;

        $valid=$modelC->validate() && $valid;

 

        if($valid)

        {

            // use false parameter to disable validation

            //$modelA->save(false);

            //$modelB->save(false);

            //$modelC->save(false);

            

             $this->redirect(array('view',

                 'id_compagnia'=>$modelC->id_compagnia,

                 'id_tpa'=>$modelB->id_tpa,

                 'id_tpb'=>$modelB->id_tpb,

                 'data_a'=>$modelA->data_a,

                 'data_b'=>$modelA->data_b,

             ));

        }

    }

    $this->render('new',array('modelA'=>$modelA,'modelB'=>$modelB,'modelC'=>$modelC));

    

}

        

 	/**

	 * Updates a particular model.

	 * If update is successful, the browser will be redirected to the 'view' page.

	 * @param integer $id the ID of the model to be updated

	 */

	/*public function actionUpdate($id)

	{

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


		// Uncomment the following line if AJAX validation is needed

		// $this->performAjaxValidation($model);


	/*	if(isset($_POST['Booking']))

		{

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

			if($model->save())

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

		}


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

			'model'=>$model,

		));

	}*/


	/**

	 * Lists all models.

	 */

	public function actionIndex()

	{

		$dataProvider=new CActiveDataProvider('Compagnie');

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

			'dataProvider'=>$dataProvider,

		));

	}


	/**

	 * Manages all models.

	 */

	public function actionAdmin()

	{

		$model=new Booking('search');

		$model->unsetAttributes();  // clear any default values

		if(isset($_GET['Booking']))

			$model->attributes=$_GET['Booking'];


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

			'model'=>$model,

		));

	}


	/**

	 * Returns the data model based on the primary key given in the GET variable.

	 * If the data model is not found, an HTTP exception will be raised.

	 * @param integer $id the ID of the model to be loaded

	 * @return Booking the loaded model

	 * @throws CHttpException

	 */

	public function loadModel($id)

	{

                $modelC=Compagnie::model()->findByPk($id);

                if(($modelC===null)) {

			throw new CHttpException(404,'The requested page does not exist.');

                }

                return $modelC;

	}


	/**

	 * Performs the AJAX validation.

	 * @param Booking $model the model to be validated

	 */

         protected function performAjaxValidation($models)

         {

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

            {

                echo CActiveForm::validate($models);

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

            }

         }

        

        

        public function actionSelectTpb()

        {

            $id_tpa = $_POST['Tratte']['id_tpa'];

            

            

            $sql='SELECT DISTINCT tpb.id_tpb, tpb.np FROM tpb, tratte WHERE tratte.id_tpa =' . $id_tpa . ' AND tratte.id_tpb = tpb.id_tpb';

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

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

            $lista=$command->queryAll(); 

            $lista = CHtml::listData($lista,'id_tpb','np');

            

            echo CHtml::tag('option', array('id_tpb' => ''), 'Seleziona', true);

            

            foreach ($lista as $id_tpb => $np){

              echo CHtml::tag('option',array('value'=>$id_tpb),CHtml::encode($np), true );

            }

        }

        

        

        public function actionSelectCompagnia()

        {

            $id_tpa = $_POST['Tratte']['id_tpa'];

            $id_tpb = $_POST['Tratte']['id_tpb'];

            

            

            $sql='SELECT * FROM tratte t1, collegamenti t2, compagnie t3 WHERE t1.id_tpa =' . $id_tpa . ' AND t1.id_tpb =' . $id_tpb . ' AND t1.id_tratta = t2.id_tratta AND t2.id_compagnia = t3.id_compagnia';

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

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

            $lista=$command->queryAll(); 

            $lista = CHtml::listData($lista,'id_compagnia','nc');

            

           foreach ($lista as $id_compagnia => $nc){

              echo CHtml::tag('option',array('value'=>$id_compagnia),CHtml::encode($nc), true );

            }

   

        }    


        

 

}



i models:

Tratte.php




<?php


/**

 * This is the model class for "tratte".

 *

 * The followings are the available columns in table 'tratte':

 * @property integer $id_tratta

 * @property integer $id_tpa

 * @property integer $id_tpb

 *

 * The followings are the available model relations:

 * @property Collegamenti[] $collegamentis

 * @property Tpa $tpa

 */

class Tratte extends CActiveRecord

{

	/**

	 * @return string the associated database table name

	 */

	public function tableName()

	{

		return 'tratte';

	}


	/**

	 * @return array validation rules for model attributes.

	 */

	public function rules()

	{

		// NOTE: you should only define rules for those attributes that

		// will receive user inputs.

		return array(

			array('id_tpa, id_tpb', 'required'),

			// The following rule is used by search().

			// @todo Please remove those attributes that should not be searched.

			array('id_tratta, id_tpa, id_tpb', 'safe', 'on'=>'search'),

		);

	}


	/**

	 * @return array relational rules.

	 */

	public function relations()

	{

		// NOTE: you may need to adjust the relation name and the related

		// class name for the relations automatically generated below.

		return array(

			'collegamentis' => array(self::HAS_MANY, 'Collegamenti', 'id_tratta'),

			'tpa' => array(self::HAS_ONE, 'Tpa', 'id_tpa'),

		);

	}


	/**

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

	 */

	public function attributeLabels()

	{

		return array(

			'id_tratta' => 'Id Tratta',

			'id_tpa' => 'Seleziona il porto di partenza',

			'id_tpb' => 'Seleziona il porto in Sardegna',

		);

	}


	/**

	 * Retrieves a list of models based on the current search/filter conditions.

	 *

	 * Typical usecase:

	 * - Initialize the model fields with values from filter form.

	 * - Execute this method to get CActiveDataProvider instance which will filter

	 * models according to data in model fields.

	 * - Pass data provider to CGridView, CListView or any similar widget.

	 *

	 * @return CActiveDataProvider the data provider that can return the models

	 * based on the search/filter conditions.

	 */

        

 

	public function search()

	{

		// @todo Please modify the following code to remove attributes that should not be searched.


		$criteria=new CDbCriteria;


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

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

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


		return new CActiveDataProvider($this, array(

			'criteria'=>$criteria,

		));

	}


	/**

	 * Returns the static model of the specified AR class.

	 * Please note that you should have this exact method in all your CActiveRecord descendants!

	 * @param string $className active record class name.

	 * @return Tratte the static model class

	 */

	public static function model($className=__CLASS__)

	{

		return parent::model($className);

	}

}




Compagnie.php




<?php


/**

 * This is the model class for table "compagnie".

 *

 * The followings are the available columns in table 'compagnie':

 * @property integer $id_compagnia

 * @property string $nc

 * @property string $cod

 *

 * The followings are the available model relations:

 * @property Collegamenti[] $collegamentis

 * @property Collegamenti $idCompagnia

 */

class Compagnie extends CActiveRecord

{

	/**

	 * @return string the associated database table name

	 */

	public function tableName()

	{

		return 'compagnie';

	}


	/**

	 * @return array validation rules for model attributes.

	 */

	public function rules()

	{

		// NOTE: you should only define rules for those attributes that

		// will receive user inputs.

		return array(

			array('id_compagnia', 'required'),

			//array('nc', 'length', 'max'=>20),

			//array('cod', 'length', 'max'=>2),

			// The following rule is used by search().

			// @todo Please remove those attributes that should not be searched.

			array('id_compagnia', 'required','on'=>'view'),

		);

	}


	/**

	 * @return array relational rules.

	 */

	public function relations()

	{

		// NOTE: you may need to adjust the relation name and the related

		// class name for the relations automatically generated below.

		return array(

			'collegamentis' => array(self::HAS_MANY, 'Collegamenti', 'id_compagnia'),

			'idCompagnia' => array(self::BELONGS_TO, 'Collegamenti', 'id_compagnia'),

		);

	}


	/**

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

	 */

	public function attributeLabels()

	{

		return array(

			'id_compagnia' => 'Scegli con che compagnia viaggiare',

		);

	}


	/**

	 * Retrieves a list of models based on the current search/filter conditions.

	 *

	 * Typical usecase:

	 * - Initialize the model fields with values from filter form.

	 * - Execute this method to get CActiveDataProvider instance which will filter

	 * models according to data in model fields.

	 * - Pass data provider to CGridView, CListView or any similar widget.

	 *

	 * @return CActiveDataProvider the data provider that can return the models

	 * based on the search/filter conditions.

	 */

	public function search()

	{

		// @todo Please modify the following code to remove attributes that should not be searched.


		$criteria=new CDbCriteria;


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

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

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


		return new CActiveDataProvider($this, array(

			'criteria'=>$criteria,

		));

	}


	/**

	 * Returns the static model of the specified AR class.

	 * Please note that you should have this exact method in all your CActiveRecord descendants!

	 * @param string $className active record class name.

	 * @return Compagnie the static model class

	 */

	public static function model($className=__CLASS__)

	{

		return parent::model($className);

	}

}




Dati.php




<?php

class Dati extends CFormModel

{

	public $data_a;

	public $data_b;

        

        public function rules()

	{

		// NOTE: you should only define rules for those attributes that

		// will receive user inputs.

		return array(

			array('data_a, data_b', 'required', 'on'=>'new'),

		);

	}

        

        	public function attributeLabels()

	{

		return array(

			'data_a'=>'Seleziona la data nella quale vorresti partire',

                        'data_b'=>'Seleziona la data per il ritorno',

		);

	}

        

      	public static function model($className=__CLASS__)

	{

		return parent::model($className);

        }


        

}



e infine la vista:




<?php

/* @var $this BookingController */

/* @var $modelA Dati */

/* @var $modelB Tratte */

/* @var $modelC Compagnie */

/* @var $form CActiveForm */

?>


<div class="form">


    


<?php   $form=$this->beginWidget('CActiveForm', array(

	'id'=>'booking-form',

	// Please note: When you enable ajax validation, make sure the corresponding

	// controller action is handling ajax validation correctly.

	// There is a call to performAjaxValidation() commented in generated controller code.

	// See class documentation of CActiveForm for details on this.

	'enableAjaxValidation'=>true,

)); ?>




        

        

        

        

     	<p class="note">Fields with <span class="required">*</span> are required.</p>


	<?php echo $form->errorSummary(array($modelA,$modelB,$modelC)); ?>

	<div class="row">

		<?php echo $form->labelEx($modelB,'id_tpa'); ?>

		<?php echo $form->dropDownList($modelB,'id_tpa',

                   CHtml::listData(Tpa::model()->findAll(),'id_tpa','np'),

                        array(

                            'ajax'=>array(

                              'type'=>'POST',

                              'url'=>CController::createUrl('Booking/SelectTpb'),

                              'update'=>'#'.CHtml::activeId($modelB,'id_tpb'),

                                

                            ),'prompt'=>'Seleziona'

                            

                            

                        )

                        ); ?>

		<?php echo $form->error($modelB,'id_tpa'); ?>

	</div>

        <div class="row">

		<?php echo $form->labelEx($modelB,'id_tpb'); ?>

		<?php echo $form->dropDownList($modelB,'id_tpb',

                   CHtml::listData(Tpb::model()->findAll(),'id_tpb','np'),

                        array(

                            'ajax'=>array(

                              'type'=>'POST',

                              'url'=>CController::createUrl('Booking/SelectCompagnia'),

                              'update'=>'#'.CHtml::activeId($modelC,'id_compagnia'),

                                

                            ),'prompt'=>'Seleziona'

                            

                            

                        )

                        ); ?>

                        

                        

                        <?php echo $form->error($modelB,'id_tpb'); ?>

	</div>

        

        <div class="row">

		<?php echo $form->labelEx($modelC,'id_compagnia'); ?>

		<?php echo $form->dropDownList($modelC,'id_compagnia',array('0'=>'compagnie')); ?>

		<?php echo $form->error($modelC,'id_compagnia'); ?>

	</div>        


        <div class="row">

                <?php echo $form->labelEx($modelA,'data_a'); ?>

<?php

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

        'model' => $modelA,

        'attribute' => 'data_a',

        'name'=>"Dati[data_a]", // the name of the field

        'value'=>$modelA->data_a,  // pre-fill the value


        'options' => array(

                        'showAnim'=>'fold',

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

                        'changeMonth'=>true,

                        'minDate' => '01-04-2014',      // minimum date

                        'maxDate' => '31-10-2014',      // maximum date

                        ),

                        'htmlOptions' => array(

                        'style' => 'height:20px;'

                        ),

                        ));

*/?>   

                <?php echo $form->error($modelA,'data_a'); ?>

        </div>

        

        

        <div class="row">

                <?php echo $form->labelEx($modelA,'data_b');

                  ?>

                <?php

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

                    'model'=>$modelA,

                    'attribute'=>"data_b",  // name of post parameter

                    'options'=>array(

                        'showAnim'=>'fold',

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

                        'changeMonth'=>true,

                        'minDate' => '01-04-2014',      // minimum date

                        'maxDate' => '31-10-2014',      // maximum date

                        'beforeShow' => 'js:function(){

                            var selectedDate=$("#'.CHtml::activeId($modelA,'data_a').'").datepicker("getDate");

                            

                            $(this).datepicker("option","minDate",selectedDate);

                        }'


                    ),

                    'htmlOptions'=>array(

                        'style'=>'height:20px;',

                    ),

                    ));

                ?>  

                <?php echo $form->error($modelA,'data_b'); ?>

        </div>




        

        

        

        

        <div class="row buttons">

		<?php echo CHtml::submitButton('Verifica'); ?>

	</div>

        

       

</div>


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



Ora… per quanto concerne modelB e modelC … in linea di massima funzionano:

mentre non riesco ad ottenere alcuna variabile da modelA … ne usando datepicker, ne come semplice textfield.

grazie a chiunque vorrà darmi una mano :)