Yii Framework Forum: Extending Cdbtransaction - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Extending Cdbtransaction Rate Topic: -----

#1 User is offline   Keith 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 835
  • Joined: 04-March 10
  • Location:UK

Posted 12 October 2012 - 10:15 AM

I currently use a behavior to implement history logging, which uses afterFind() and beforeSave() to determine any changes and log them to a history table (MySQL archive engine).

The archive table format doesn't support transactions, so my existing solution could show history for an update that never occurred, as a result of the actual changes being rolled back.

I've thought of a way to solve this:
  • Override CDbTransaction
  • Add a private array to hold the outstanding history
  • Add a method to append to the history array (called from the behavior)
  • Override CDbTransaction::commit() to save all history after calling the parent implementation
  • Update the behavior to log history to the active transaction if there is one, or output straight to the history table if not


This would enable the history to be logged only if the transaction completes successfully.
Unfortunately, the CDbTransaction class is hardcoded in CDbConnection::beginTransaction().

I'm intending to extend CDbConnection and override the beginTransaction() method, so that I can instantiate my new transaction class.

Is this the best way to approach this problem, or is there a more sensible option?
0

#2 User is offline   Rodrigo Coelho 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 644
  • Joined: 05-August 10
  • Location:Rio de Janeiro, Brazil

Posted 12 October 2012 - 05:51 PM

Spots of this kind are the few places where Yii isn't much extensible.
I'm interested in the solution, too.
Rodrigo Coelho


Check my extension
giix: a code generator for Yii. Posted Image


The complete beginner's study guide for the Yii Framework
0

#3 User is offline   Keith 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 835
  • Joined: 04-March 10
  • Location:UK

Posted 15 October 2012 - 05:00 AM

I'm about to go ahead and implement this. Any last minute suggestions anyone?
0

#4 User is offline   Keith 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 835
  • Joined: 04-March 10
  • Location:UK

Posted 16 October 2012 - 05:11 AM

Okay, I don't like how I've had to override a private instance variable, but this implementation seems to work.

class DbConnection extends CDbConnection
{
	private $_transaction; // Override parent
	
	public function beginTransaction() 
	{ 
		Yii::trace('Starting transaction', 'DbConnection'); 
		$this->setActive(true); 
		$this->getPdoInstance()->beginTransaction(); 
		return $this->_transaction=new DbTransaction($this); 
	}
}

class DbTransaction extends CDbTransaction {
	
	private $outstandingHistory = array();
	
	public function appendHistory($history)
	{
		$this->outstandingHistory[] = $history;
	}
	
	public function commit()
	{
		parent::commit();
		
		foreach ($this->outstandingHistory as $history)
			$history->save();
		
		$this->outstandingHistory = array();
	}
}


Each element of outstandingHistory is a History model instance. If there's an active transaction, the history logging behavior appends the instance to this array. If there's no active transaction, the behavior simply saves the History model instance.

I figured I'd post it in case anyone else needs similar functionality in the future.
3

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users