1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
<?php class MyClass { public function doSomething() { $sql = SQL::getInstance(); $mode = $sql->setErrorMode(SQL::THROW_EXCEPTION); try { $sql->startTransaction($useTransaction); foreach ($values as $value) { $value->update(false); } $sql->doCommit($useTransaction); $sql->setErrorMode($mode); } catch (Exception $e) { $sql->cleanEndTransaction($useTransaction, $mode, $e, 'MyException'); return null; } } }
Refactorings
No refactoring yet !
Michał Pochwała
July 29, 2010, July 29, 2010 10:58, permalink
I hope it will help you.
A little comment to the naming convention for the methods. To have a method with transaction support use tx prefix for method name, eg:
* txDoSomething()
* txDoSomethingElse()
interface only for marking the transactional behaviour
1
interface Transactional{}
class which needs access to transactions (some kind of aspect)
1 2 3 4 5 6 7 8 9 10 11 12 13
class MyClass implements Transactional{
private function __construct(){}
public function noTransactionMethod($testParam1, $testParam2){
echo "the noTransactionMethod invoked with params ".$testParam1. ' and '.$testParam2;
}
public function txWithTransactionMethod($testParam1, $testParam2){
echo " the txWithTransactionMethod invoked with params ".$testParam1. ' and '.$testParam2.' ';
}
public static function createInstance(){
$myClassObject = new MyClass();
return new TransactionalProxy($myClassObject);
}
}
proxy which add transactional 'aspect'
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
class TransactionalProxy{
private $service;
public function __construct(Transactional $service){
$this->service = $service;
}
public function __call($methodName,$args){
if( preg_match('/^tx.+/',$methodName )){
return $this->invoke_with_transaction($methodName,$args);
}else{
return $this->invokde_without_transaction($methodName,$args);
}
}
private function invoke_with_transaction($methodName,$args){
echo "handle transaction start <<";
$results = $this->invoke($methodName,$args);
echo " >>handle transaction end";
return $results;
}
private function invokde_without_transaction($methodName,$args){
$this->invoke($methodName,$args);
}
private function invoke($methodName,$args){
return call_user_func_array(array($this->service, $methodName), $args);
}
}
test code
1 2 3 4 5 6
$tester = MyClass::createInstance();
echo "\r\n=======================\r\n";
$tester->noTransactionMethod("first","second");
echo "\r\n=======================\r\n";
$tester->txWithTransactionMethod("third","fourth");
echo "\r\n=======================\r\n";
I've got this pattern all over my code, to ensure that transaction are running correctly (esp. since they are nested). In PHP 5.3 I could extract the small payload ($value->update) into a neat little anonymous function and I'm done. But it has to be compatible PHP 5.1. Any ideas, how to not repeat this code over and over again *without* using create_function?