Exporting A Row From A Table To Another With Same Fields

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:


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')); ?>&nbsp;

<?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.

please post the complete error text so i could help you

Here it is :)


PHP notice


Trying to get property of non-object


C:\xampp\htdocs\exporttest\protected\controllers\SiteController.php(137)


125     }

126     Yii::app()->user->setFlash('saved',Yii::t('ui','Data successfully saved!'));

127     $this->redirect(array('site/index','view'=>'index'));

128     }

129 

130     public function actionExportSostanza()

131         {

132             if(isset($_POST['SostanzaExport']['export']))

133                 {

134                     foreach ($_POST['SostanzaExport']['export'] as $row){

135 

136                         $exportRow = new SostanzaExport;

137                         $exportRow->attributes = $row->attributes;

138                         $exportRow->id = null; //(if it's composite it's going to need more assignments than this)

139                         $exportRow->isNewRecord = true;

140                         $exportRow->save();

141                             }

142     

143                 }

144     $this->redirect(array('site/index','view'=>'index'));

145     }

146 }


Stack Trace

#0 	

+

 C:\xampp\htdocs\yii\framework\web\actions\CInlineAction.php(49): SiteController->actionExportSostanza()

#1 	

+

 C:\xampp\htdocs\yii\framework\web\CController.php(308): CInlineAction->runWithParams(array())

#2 	

+

 C:\xampp\htdocs\yii\framework\web\CController.php(286): CController->runAction(CInlineAction)

#3 	

+

 C:\xampp\htdocs\yii\framework\web\CController.php(265): CController->runActionWithFilters(CInlineAction, array())

#4 	

+

 C:\xampp\htdocs\yii\framework\web\CWebApplication.php(282): CController->run("exportSostanza")

#5 	

+

 C:\xampp\htdocs\yii\framework\web\CWebApplication.php(141): CWebApplication->runController("site/exportSostanza")

#6 	

+

 C:\xampp\htdocs\yii\framework\base\CApplication.php(169): CWebApplication->processRequest()

#7 	

–

 C:\xampp\htdocs\exporttest\index.php(13): CApplication->run()


08 defined('YII_DEBUG') or define('YII_DEBUG',true);

09 // specify how many levels of call stack should be shown in each log message

10 defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);

11 

12 require_once($yii);

13 Yii::createWebApplication($config)->run();



fine it’s simple and clear in line 134 $row is not a stdClass

if


$_POST['SostanzaExport']['export']

contain the your attributes


'id'


'famiglia_sostanza_id'


'codice'


'descrizione'

simply massive assign:


$exportRow->attributes = $_POST['SostanzaExport']['export']

or just remove attributes from $row->attributes so it will be like


$exportRow->attributes = $row;