开发者

perform several actions in php

According to you, what is the best solution in PHP to ensure the course of several php functions ? For example function A must return True to initiate the B function, and the B function must return True to initiate another function..开发者_如何学运维.

Is there a system like Rollback / Commit in SQL to ensure that in PHP please ?

Thank you.


Doing a chain of functions would look something like this:

try {
    if(!functionA()) {
        throw new Exception("Error message here", 100); // 100 can be any code, as long as it's unique to the other throw exception codes
    }

    if(!functionB()) {
        throw new Exception("Error message here", 101);
    }

    if(!functionC()) {
        throw new Exception("Error message here", 102);
    }
} catch(Exception $e) { 
    /**
     * Do some actions depending on the error code of the exception (100, 101, 102)
     */
}

But if I understand correctly you want to perform a serie of operations and only if they are all successful you want them to be final, otherwise you want to undo all the operations?

In this case it is hard to tell how you should implement this, cause you don't tell what you want to achieve.

But I can give you some advise. Most operations that are not reversable do have many possible checks. For example, if you want to be sure a file will be deleted from the filesystem you can first check if the file is writable (is_writable) and even exists (file_exists). If you first do all the checks of all operations and afterwards execute the operations, you can be pretty sure they will be executed successfully. Ofcourse it's possible you forget checks, or some things can't be checked, but I don't see an other option to fix this.


There's no "rollback" available with php.

However if you work with exceptions, you can try your code, and as soon as you get an exception, call a rollback function in the catch section.

Pseudo code :

try {
  your_function_1(); // must throw exceptions on error
  your_function_2(); // must throw exceptions on error
} catch(Exception $e){
  your_rollback_code();
}


About "initiating functions", based on result of other functions - depends on context of functions. Few options:

if ( A() ) {
    if ( B() ) {
        anotherFunction();
    }
}

or

if ( A() && B() && anotherFunction() ) {
}

or

if ( A() && B() ) {
    anotherFunction();
}

In most cases, I would do the last one (if ( a and b ) { do c }).


If you have that many things to run through then it is best that you use a state machine.

In its simplest for this is just a loop while a "state" variable does not have the state "done". Every time one of the functions reports it is done, you just move up to the next state.

Simple example:

$nState = 0;
while ($nState != 3)
{
   switch ($nState)
   {
      case 0 : if (function1()) $nState = 1; break;
      case 1 : if (function2()) $nState = 2; break;
      case 2 : if (function3()) $nState = 3; break;
   }
}

Added advantage is that you can also go back. Obviously for clarity you can make the states constants and so on.

The state machine has the advantage that it keeps things neat and clear, even with a lot of functions.

I'm assuming here that the functions don't necessarily succeed on their first try and that sometimes you have to run them multiple times. If that is not the case, Stegeman's answer is the easier one.


You can have a definition array:

$callbacks = array
(
    array
    (
        'function' => 'function_1',
        'rollback' => 'function_r1',
        'arguments' => array(1),
    ),

    array
    (
        'function' => 'function_2',
        'rollback' => 'function_r2',
        'arguments' => array(1, 2),
    ),

    array
    (
        'function' => 'function_3',
        'rollback' => 'function_r3',
        'arguments' => array(1, 2, 3),
    ),
);

And do something like this:

$callbacks = array_values($callbacks);

foreach ($callbacks as $key => $callback)
{
    if (call_user_func_array($callback['function'], $callback['arguments']) !== true)
    {
        // failed, calling necessary rollbacks in reverse order

        foreach (array_reverse(array_slice($callbacks, 0, $key)) as $rollback)
        {
            if (is_callable($rollback['rollback']) === true)
            {
                call_user_func_array($rollback['rollback'], $rollback['arguments']);
            }
        }

        break;
    }

    // success
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜