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