Hi everyone, I'm new to Yii and I'd need some help. Please forgive my grammar mistakes but english is not my native language. Now on the problem:
I need to copy a row from a table located in a database to a clone table I created in another database. What I'm trying to implement is an "export" feature from the mother database to a custom istance of my application. This is my original model generated with Gii:
Then I created an extension of CActiveRecord in order to get access to a differnt db ("dbExport") connection with the entity which would represent clone table rows:
Which was extended by the new entity where I overrided the method getDbConnection to get the correct destination database
finally I added this snippet to my SiteController to implement the cloning and save
This refers to the widget I placed in my view, which is as follows:
The widget correctly brings up both lists from the two databases. However, if I move an item from column "source" to "export" and then click on the "save" button I get an error pointing out that I'm "Trying to get property of non-object". What am I missing here? I searched around on the web and on the forums but I was unable to find any clue or alternative. Let me thank you anticipately for your time and help, it would be much appreciated.
I need to copy a row from a table located in a database to a clone table I created in another database. What I'm trying to implement is an "export" feature from the mother database to a custom istance of my application. This is my original model generated with Gii:
class Sostanza extends CActiveRecord { /** * Returns the static model of the specified AR class. * @param string $className active record class name. * @return Sostanza the static model class */ public static function model($className=__CLASS__) { return parent::model($className); } /** * @return string the associated database table name */ public function tableName() { return 'sostanza'; } /** * @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('famiglia_sostanza_id', 'numerical', 'integerOnly'=>true), array('codice, descrizione', 'safe'), // The following rule is used by search(). // Please remove those attributes that should not be searched. array('id, famiglia_sostanza_id, codice, descrizione', '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( 'famigliaSostanza' => array(self::BELONGS_TO, 'FamigliaSostanza', 'famiglia_sostanza_id'), ); } /** * @return array customized attribute labels (name=>label) */ public function attributeLabels() { return array( 'id' => 'ID', 'famiglia_sostanza_id' => 'Famiglia Sostanza', 'codice' => 'Codice', 'descrizione' => 'Descrizione', ); } /** * Retrieves a list of models based on the current search/filter conditions. * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions. */ public function search() { // Warning: Please modify the following code to remove attributes that // should not be searched. $criteria=new CDbCriteria; $criteria->compare('id',$this->id); $criteria->compare('famiglia_sostanza_id',$this->famiglia_sostanza_id); $criteria->compare('codice',$this->codice,true); $criteria->compare('descrizione',$this->descrizione,true); return new CActiveDataProvider($this, array( 'criteria'=>$criteria, )); } /** * @param int $famiglia_sostanza_id * @return array for listbuilder (id => name) */ public function findSostanzaByFamiglia($famiglia_sostanza_id) { $criteria=array( 'select'=>"id, descrizione", 'condition'=>'famiglia_sostanza_id='.$famiglia_sostanza_id, 'order'=>'id', ); return CHtml::listData($this->findAll($criteria),'id','descrizione'); } public function updateSostanzaFamiglia($id, $famiglia_sostanza_id) { $model=$this->findByPk($id); $model->famiglia_sostanza_id=$famiglia_sostanza_id; $model->update('famiglia_sostanza_id'); } public function findAllSostanza() { $criteria=array( 'select'=>"id, descrizione", 'condition'=> '1=1', 'order'=>'id', ); return CHtml::listData($this->findAll($criteria),'id','descrizione'); } }
Then I created an extension of CActiveRecord in order to get access to a differnt db ("dbExport") connection with the entity which would represent clone table rows:
class ExportedEntity extends CActiveRecord { private static $dbExport = null; protected static function getDbExportConnection() { if (self::$dbExport!== null) return self::$dbExport; else { self::$dbExport = Yii::app()->dbExport; if (self::$dbExport instanceof CDbConnection) { self::$dbExport->setActive(true); return self::$dbExport; } else throw new CDbException(Yii::t('yii','Active Record requires a "db" CDbConnection application component.')); } } }
Which was extended by the new entity where I overrided the method getDbConnection to get the correct destination database
<?php class SostanzaExport extends ExportedEntity{ public function getDbConnection(){ return self::getDbExportConnection(); } public static function model($className=__CLASS__) { return parent::model($className); } /** * @return string the associated database table name */ public function tableName() { return 'sostanza'; } /** * @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('famiglia_sostanza_id', 'numerical', 'integerOnly'=>true), array('codice, descrizione', 'safe'), // The following rule is used by search(). // Please remove those attributes that should not be searched. array('id, famiglia_sostanza_id, codice, descrizione', '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( 'famigliaSostanza' => array(self::BELONGS_TO, 'FamigliaSostanza', 'famiglia_sostanza_id'), ); } /** * @return array customized attribute labels (name=>label) */ public function attributeLabels() { return array( 'id' => 'ID', 'famiglia_sostanza_id' => 'Famiglia Sostanza', 'codice' => 'Codice', 'descrizione' => 'Descrizione', ); } /** * Retrieves a list of models based on the current search/filter conditions. * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions. */ public function search() { // Warning: Please modify the following code to remove attributes that // should not be searched. $criteria=new CDbCriteria; $criteria->compare('id',$this->id); $criteria->compare('famiglia_sostanza_id',$this->famiglia_sostanza_id); $criteria->compare('codice',$this->codice,true); $criteria->compare('descrizione',$this->descrizione,true); return new CActiveDataProvider($this, array( 'criteria'=>$criteria, )); } /** * @param int $famiglia_sostanza_id * @return array for listbuilder (id => name) */ public function findSostanzaByFamiglia($famiglia_sostanza_id) { $criteria=array( 'select'=>"id, descrizione", 'condition'=>'famiglia_sostanza_id='.$famiglia_sostanza_id, 'order'=>'id', ); return CHtml::listData($this->findAll($criteria),'id','descrizione'); } public function updateSostanzaFamiglia($id, $famiglia_sostanza_id) { $model=$this->findByPk($id); $model->famiglia_sostanza_id=$famiglia_sostanza_id; $model->update('famiglia_sostanza_id'); } public function findAllSostanza() { $criteria=array( 'select'=>"id, descrizione", 'condition'=> '1=1', 'order'=>'id', ); return CHtml::listData($this->findAll($criteria),'id','descrizione'); } /* public function exportSostanza(){ $this->save(); } */ }
finally I added this snippet to my SiteController to implement the cloning and save
public function actionExportSostanza() { if(isset($_POST['Sostanza']['export'])) { foreach ($_POST['Sostanza']['export'] as $row){ $exportRow = new SostanzaExport; $exportRow->attributes = $row->attributes; $exportRow->id = null; $exportRow->isNewRecord = true; $exportRow->save(); } } $this->redirect(array('site/index','view'=>'index')); }
This refers to the widget I placed in my view, which is as follows:
<?php echo CHtml::beginForm($this->createUrl('exportSostanza')); ?> <?php $this->widget('ext.widgets.multiselects.XMultiSelects',array( 'leftTitle'=>'DB Source', 'leftName'=>'Sostanza[source][]', 'leftList'=>Sostanza::model()->findAllSostanza(), 'rightTitle'=>'DB Exported', 'rightName'=>'SostanzaExport[export][]', 'rightList'=>SostanzaExport::model()->findAllSostanza(), 'size'=>20, 'width'=>'200px', )); ?> <br /> <?php echo CHtml::submitButton(Yii::t('ui', 'Save'), array('class'=>'btn btn-primary')); ?> <?php echo CHtml::endForm(); ?>
The widget correctly brings up both lists from the two databases. However, if I move an item from column "source" to "export" and then click on the "save" button I get an error pointing out that I'm "Trying to get property of non-object". What am I missing here? I searched around on the web and on the forums but I was unable to find any clue or alternative. Let me thank you anticipately for your time and help, it would be much appreciated.