Implementing Code Igniter “Roll Back” System
If you need to ensure that your system or database does not have half complete executions which might have halted due to failures, you have two obvious solutions. One is to try and pre-verify everything before you start your execution but even that is not bulletproof. A more elegant approach is to push each equal and opposite actions to a stack and cause the stack to pop and execute on any failure. Read on to see an implementation.
1. Add the lib_rollback.php class to your library folder
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* A class responsible for keeping tracking and rolling back actions
* It has an internal stack on which php actions gets executed. The pushed actions
* are equal opposites of action being performed this way if any error occurs the stack
* is poppped and actions are undone.
*/
class Lib_rollback
{
/**
* An array used as a stack to push changes to undo in case of failure
*
* @var array
**/
private $rollbackStack;
/**
* An object reference to the ci object
*
* @var obj
**/
protected $ci;
/**
* Constructor
*/
function Lib_rollback()
{
// Initiliaze the CI Object as reference
$this->ci =&get_instance();
// Reset the stack
$this->resetStack();
}
/**
* Reset the stack by emptying the array
*/
function resetStack()
{
$this->rollbackStack = array();
}
/**
* Push an action onto the stack. The action should be a valid php executable action
* which will get evaluated
*
* @param string $inAction The php action which will be evaluated
* @return void
*/
function pushAction($inAction)
{
array_push($this->rollbackStack, $inAction);
}
/**
* This iniates the roll back action and evaluates and executes every action on the stack.
* This is triggered if an error occurs to prevent partial runs
*
*/
function rollBackNow()
{
while(count($this->rollbackStack) > 0)
{
$currentTask = array_pop($this->rollbackStack);
eval($currentTask);
}
}
}
2. Autoload the library
- Edit the file config > autload.php and add “lib_rollback” to the $autoload['libraries']
(i.e: $autoload['libraries'] = array(‘database’, ‘session’, ‘lib_rollback’);)
3. Overload the exceptions to trigger the stack rollback
Now that the stack is setup we need an automatic way for it to be called in case of errors. This can be done by overoading the Exceptions class of code igniter in particular two functions, show_error() and show_php_error(). These are two functions which get called when something goes wrong.
So create a file called MY_Exceptions.php inside the “application > core” folder. In this file start it like so
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Exceptions extends CI_Exceptions {
function show_error($heading, $message, $template = 'error_general', $status_code = 500)
{
$this->ci =&get_instance();
$this->ci->lib_rollback->rollBackNow();
//....
}
function show_php_error($severity, $message, $filepath, $line)
{
$this->ci =&get_instance();
$this->ci->lib_rollback->rollBackNow();
//....
}
}
Inside this class copy paste the original show_error() and show_php_error() functions into it then at the top of each call your rollback function.
4. Example usage
$tempFolder = "C:/WebRoot/tmp/active"
mkdir($tempFolder );
// Push the action to a stack to propery undo in case of mid failure
$this->lib_rollback->pushAction("rmdir($tempFolder);");
That should do it! Don’t forget that what you push must be a valid php command with an ending semi colon.