Hola a todos.
Tengo algo muy similar.
Me gustaría traer el precio de un producto y mostrarlo en un campo del formulario (El campo no esta generado por el crud - No se inserta en la base de datos - Solo es para saber cuanto cuesta el producto seleccionado).
Algo a tener en cuenta es que tengo 1 formulario con 2 modelos.
Voy a compartirles el código:
_form.php
<?php
/* @var $this FacturaController */
/* @var $model Factura */
/* @var $form CActiveForm */
?>
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'factura-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"><?php echo Yii::t('app','Fields with');?> <span class="required">*</span> <?php echo Yii::t('app','are required.');?></p>
<?php echo $form->errorSummary(array($model, $modelDetalle)); ?>
<div class="row">
<?php echo $form->labelEx($model,'fechaVenta'); ?>
<?php $this->widget ('application.extensions.CJuiDateTimePicker.CJuiDateTimePicker',
array(
'model'=>$model, //Model object
'attribute'=>'fechaVenta', //attribute name
'value'=>$model->fechaVenta,
'mode'=>'datetime', //use "time","date" or "datetime" (default)
'language'=>'es',
'options'=>array(
'regional'=>'es',
'autoSize'=>'true',
'dateFormat'=>'yy-mm-dd',
'timeformat'=>'hh:mm',
'changeMonth'=>'true',
'changeYear'=>'true',
'yearRange'=>'-10:+0',
//'ampm'=>'true',
'timeText'=>'Horario',
'hourText'=>'Hora',
'minuteText'=>'Minuto',
) // jquery plugin options
));
?>
<?php echo $form->error($model,'fechaVenta'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'idVendedor'); ?>
<?php echo $form->dropDownList($model,'idVendedor', CHtml::listData(Vendedor::model()->findAll("activo=1"), 'idVendedor', 'nombresVendedor')); ?>
<?php echo $form->error($model,'idVendedor'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($modelDetalle,'idProducto'); ?>
<?php echo $form->dropDownList($modelDetalle,'idProducto', CHtml::listData(Producto::model()->findAll("activo=1",array('order'=>'descripcion ASC')), 'idProducto', 'descripcion')); ?>
<?php echo $form->error($modelDetalle,'idProducto'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($modelDetalle,'cantidad'); ?>
<?php echo $form->textField($modelDetalle,'cantidad'); ?>
<?php echo $form->error($modelDetalle,'cantidad'); ?>
</div>
<div class="row buttons">
<?php echo CHtml::submitButton($model->isNewRecord ? Yii::t('app','Create') : Yii::t('app','Save')); ?>
</div>
<?php $this->endWidget(); ?>
</div><!-- form -->
Se necesita tener el create.php
<?php
/* @var $this FacturaController */
/* @var $model Factura */
$this->breadcrumbs=array(
'Facturas'=>array('index'),
Yii::t('app','Create'),
);
$this->menu=array(
array('label'=>Yii::t('app','List'). ' Facturas', 'url'=>array('index')),
array('label'=>Yii::t('app','Manage'). ' Facturas', 'url'=>array('admin')),
);
?>
<h1><?php echo Yii::t('app','Create'); ?> Factura</h1>
<?php $this->renderPartial('_form', array('model'=>$model, 'modelDetalle'=>$modelDetalle)); ?>
Modelos:
Detalle.php
<?php
/**
* This is the model class for table "detalle".
*
* The followings are the available columns in table 'detalle':
* @property string $idDetalle
* @property string $idFactura
* @property string $idProducto
* @property integer $cantidad
*/
class Detalle extends CActiveRecord
{
/**
* @return string the associated database table name
*/
public function tableName()
{
return 'detalle';
}
/**
* @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('idFactura, idProducto, cantidad', 'required'),
array('cantidad', 'numerical', 'integerOnly'=>true),
array('idFactura, idProducto', 'length', 'max'=>10),
// The following rule is used by search().
// @todo Please remove those attributes that should not be searched.
array('idDetalle, idFactura, idProducto, cantidad', '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(
'producto' => array(self::BELONGS_TO, 'Producto', 'idProducto'),
'factura' => array(self::BELONGS_TO, 'Factura', 'idFactura'),
);
}
/**
* @return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
'idDetalle' => 'Id Detalle',
'idFactura' => 'Factura',
'idProducto' => 'Producto',
'cantidad' => 'Cantidad',
//'precioVenta' => 'Precio de venta',
);
}
/**
* 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('idDetalle',$this->idDetalle,true);
$criteria->compare('idFactura',$this->idFactura,true);
//$criteria->compare('idProducto',$this->idProducto,true);
$criteria->with =array('producto');
$criteria->addSearchCondition('producto.descripcion', $this->idProducto);
$criteria->compare('cantidad',$this->cantidad);
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 Detalle the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
}
Factura.php
<?php
/**
* This is the model class for table "factura".
*
* The followings are the available columns in table 'factura':
* @property string $idFactura
* @property string $fechaVenta
* @property string $idVendedor
*/
class Factura extends CActiveRecord
{
/**
* @return string the associated database table name
*/
public function tableName()
{
return 'factura';
}
/**
* @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('fechaVenta, idVendedor', 'required'),
array('idVendedor', 'length', 'max'=>10),
// The following rule is used by search().
// @todo Please remove those attributes that should not be searched.
array('idFactura, fechaVenta, idVendedor', '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(
'vendedor' => array(self::BELONGS_TO, 'Vendedor', 'idVendedor'),
);
}
/**
* @return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
'idFactura' => 'Id Factura',
'fechaVenta' => 'Fecha de venta',
'idVendedor' => 'Vendedor',
);
}
/**
* 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('idFactura',$this->idFactura,true);
$criteria->compare('fechaVenta',$this->fechaVenta,true);
$criteria->compare('idVendedor',$this->idVendedor,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 Factura the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
}
Controladores:
DetalleController.php
<?php
class DetalleController 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';
/**
* @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
);
}
/**
* Specifies the access control rules.
* This method is used by the 'accessControl' filter.
* @return array access control rules
*/
public function accessRules()
{
return array(
array('allow', // allow all users to perform 'index' and 'view' actions
'actions'=>array('index','view'),
'users'=>array('@'),
),
array('allow', // allow authenticated user to perform 'create' and 'update' actions
'actions'=>array('create','update'),
'users'=>array('admin'),
),
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('*'),
),
);
}
/**
* Displays a particular model.
* @param integer $id the ID of the model to be displayed
*/
public function actionView($id)
{
$this->render('view',array(
'model'=>$this->loadModel($id),
));
}
/**
* Creates a new model.
* If creation is successful, the browser will be redirected to the 'view' page.
*/
public function actionCreate()
{
$model=new Detalle;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['Detalle']))
{
$model->attributes=$_POST['Detalle'];
if($model->save())
$this->redirect(array('view','id'=>$model->idDetalle));
}
$this->render('create',array(
'model'=>$model,
));
}
/**
* 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['Detalle']))
{
$model->attributes=$_POST['Detalle'];
if($model->save())
$this->redirect(array('view','id'=>$model->idDetalle));
}
$this->render('update',array(
'model'=>$model,
));
}
/**
* Deletes a particular model.
* If deletion is successful, the browser will be redirected to the 'admin' page.
* @param integer $id the ID of the model to be deleted
*/
public function actionDelete($id)
{
$this->loadModel($id)->delete();
// if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser
if(!isset($_GET['ajax']))
$this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin'));
}
/**
* Lists all models.
*/
public function actionIndex()
{
$dataProvider=new CActiveDataProvider('Detalle');
$this->render('index',array(
'dataProvider'=>$dataProvider,
));
}
/**
* Manages all models.
*/
public function actionAdmin()
{
$model=new Detalle('search');
$model->unsetAttributes(); // clear any default values
if(isset($_GET['Detalle']))
$model->attributes=$_GET['Detalle'];
$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 Detalle the loaded model
* @throws CHttpException
*/
public function loadModel($id)
{
$model=Detalle::model()->findByPk($id);
if($model===null)
throw new CHttpException(404,'The requested page does not exist.');
return $model;
}
/**
* Performs the AJAX validation.
* @param Detalle $model the model to be validated
*/
protected function performAjaxValidation($model)
{
if(isset($_POST['ajax']) && $_POST['ajax']==='detalle-form')
{
echo CActiveForm::validate($model);
Yii::app()->end();
}
}
}
FacturaController.php
<?php
class FacturaController 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';
/**
* @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
);
}
/**
* Specifies the access control rules.
* This method is used by the 'accessControl' filter.
* @return array access control rules
*/
public function accessRules()
{
return array(
array('allow', // allow all users to perform 'index' and 'view' actions
'actions'=>array('index','view'),
'users'=>array('@'),
),
array('allow', // allow authenticated user to perform 'create' and 'update' actions
'actions'=>array('create','update'),
'users'=>array('admin'),
),
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('*'),
),
);
}
/**
* Displays a particular model.
* @param integer $id the ID of the model to be displayed
*/
public function actionView($id)
{
$this->render('view',array(
'model'=>$this->loadModel($id),
));
}
/**
* Creates a new model.
* If creation is successful, the browser will be redirected to the 'view' page.
*/
public function actionCreate()
{
$model=new Factura;
$modelDetalle=new Detalle;
// Uncomment the following line if AJAX validation is needed
$this->performAjaxValidation(array($model, $modelDetalle));
if(isset($_POST['Factura'], $_POST['Detalle']))
{
$model->attributes=$_POST['Factura'];
$modelDetalle->attributes=$_POST['Detalle'];
$modelDetalle->idFactura = 1;
$valid = $model->validate();
$valid = $modelDetalle->validate() && $valid;
if($valid) {
if($model->save(false)) {
$modelDetalle->idFactura = $model->idFactura;
if ($modelDetalle->save(false))
$this->redirect(array('view','id'=>$model->idFactura));
}
}
}
$this->render('create',array(
'model'=>$model,
'modelDetalle'=>$modelDetalle,
));
}
/**
* 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['Factura']))
{
$model->attributes=$_POST['Factura'];
if($model->save())
$this->redirect(array('view','id'=>$model->idFactura));
}
$this->render('update',array(
'model'=>$model,
));
}
/**
* Deletes a particular model.
* If deletion is successful, the browser will be redirected to the 'admin' page.
* @param integer $id the ID of the model to be deleted
*/
public function actionDelete($id)
{
$this->loadModel($id)->delete();
// if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser
if(!isset($_GET['ajax']))
$this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin'));
}
/**
* Lists all models.
*/
public function actionIndex()
{
$dataProvider=new CActiveDataProvider('Factura');
$this->render('index',array(
'dataProvider'=>$dataProvider,
));
}
/**
* Manages all models.
*/
public function actionAdmin()
{
$model=new Factura('search');
$model->unsetAttributes(); // clear any default values
if(isset($_GET['Factura']))
$model->attributes=$_GET['Factura'];
$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 Factura the loaded model
* @throws CHttpException
*/
public function loadModel($id)
{
$model=Factura::model()->findByPk($id);
if($model===null)
throw new CHttpException(404,'The requested page does not exist.');
return $model;
}
/**
* Performs the AJAX validation.
* @param Factura $model the model to be validated
*/
protected function performAjaxValidation($model)
{
if(isset($_POST['ajax']) && $_POST['ajax']==='factura-form')
{
echo CActiveForm::validate($model);
Yii::app()->end();
}
}
}
Y me explico una vez más, quisiera en el _form.php debajo de:
<div class="row">
<?php echo $form->labelEx($modelDetalle,'idProducto'); ?>
<?php echo $form->dropDownList($modelDetalle,'idProducto', CHtml::listData(Producto::model()->findAll("activo=1",array('order'=>'descripcion ASC')), 'idProducto', 'descripcion')); ?>
<?php echo $form->error($modelDetalle,'idProducto'); ?>
</div>
Tener un campo para traer el precio.
Gracias y espero su ayuda.