Skip to content

Instantly share code, notes, and snippets.

@hiromi2424
Created March 6, 2011 10:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hiromi2424/857196 to your computer and use it in GitHub Desktop.
Save hiromi2424/857196 to your computer and use it in GitHub Desktop.
service model example with transaction for CakePHP
<?php
class ArticlesController extends AppController {
function add() {
if (!empty($this->data)) {
if ($this->Service->transaction()->saveNewArticle($this->data)) {
$this->Session->setFlash(__('Article has been saved.', true));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('Article was not saved. Please, try again.', true));
}
}
}
}
<?php
class Service extends Overloadable2 {
function get__($name) {
return $this->$name = ClassRegistry::init($name);
}
function set__($name, &$val) {
return $this->$name =& $val;
}
function saveNewArticle($data) {
return $this->Article->add($data);
}
function &transaction($datasources = 'default') {
$ts =& $this->TransactionService->setDataSources($datasources)->setService($this);
return $ts;
}
}
<?php
App::import('Model', array('Article', 'TransactionService'));
Mock::generate('Article');
Mock::generatePartial('TransactionService', null, array('begin', 'commit', 'rollback'));
class ServiceTest extends CakeTestCase {
function startTest() {
$this->_setupMockModel('Article', 'TransactionService');
$this->Service = ClassRegistry::init('Service');
}
function endTest() {
unset($this->Service);
ClassRegistry::flush();
}
function _setupMockModel() {
$models = func_get_args();
foreach ($models as $model) {
$mockClass = 'Mock' . $model;
$Mock =& ClassRegistry::init($mockClass);
ClassRegistry::addObject($model, $Mock);
}
}
function testSuccessSaveNewArticle() {
$data = array(
'title' => 'test title',
'body' => "test\nbody",
);
$this->Service->Article->expectOnce('add');
$this->Service->Article->setReturnvalue('add', true);
$this->Service->TransactionService->expectOnce('begin');
$this->Service->TransactionService->expectOnce('commit');
$this->Service->TransactionService->expectNever('rollback');
$this->Service->transaction()->saveNewArticle($data);
}
function testFailedSaveNewArticle() {
$data = array(
'title' => 'test title',
'body' => "test\nbody",
);
$this->Service->Article->expectOnce('add');
$this->Service->Article->setReturnvalue('add', false);
$this->Service->TransactionService->expectOnce('begin');
$this->Service->TransactionService->expectNever('commit');
$this->Service->TransactionService->expectOnce('rollback');
$this->Service->transaction()->saveNewArticle($data);
}
}
<?php
class TransactionService extends Overloadable2 {
var $_ds = array('default');
var $Service;
function call__($method, $params = array()) {
$this->begin();
$result = call_user_func_array(array($this->Service, $method), $params);
if (!$result) {
$this->rollback();
return $result;
}
$this->commit();
return $result;
}
function &setDataSources($ds) {
$this->_ds = (array)$ds;
return $this;
}
function &setService(&$Service) {
$this->Service =& $Service;
return $this;
}
function begin() {
$this->_transaction(__FUNCTION__);
}
function commit() {
$this->_transaction(__FUNCTION__);
}
function rollback() {
$this->_transaction(__FUNCTION__);
}
function _transaction($method) {
foreach ($this->_ds as $ds) {
ConnectionManager::getDataSource($ds)->$method($this->Service);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment