Реализация логики повторения PHP OO и передача динамического метода и аргументов - PullRequest
1 голос
/ 10 июня 2009

Мой первый вопрос здесь.

Вопрос похож на этот: PHP: повторная попытка запроса установленное число раз или до успеха

Попробуй до успеха в ОО пути. Вот пример того, что я пытаюсь сделать:

class Creatives {

    public function run() {
        $auth_token='mypassword';
        $id=123123;
        $this->retry_till_success ( $this->getCreatives, array($auth_token, $id) );
        print $this->creatives; 
    }

    public function getCreatives($auth_token, $id) {
        $this->creatives = $this->campagin->get($auth_token, $id);      
    }

    private function retry_till_success($method, $args) {
        do {
            $try_again = false;
            try {
                /* how to call the method with */
                /* call user method with params pass */
                /* do until success */
            } catch (SoapFault $fault) {
                if($fault->faultstring== 'couldnt connect to host')
                    $try_again=true;
            }
        } while ($try_again);
    }
}

Я читал о call_user_func, но не знаю, смогу ли я использовать его внутри класса, Мне нужно добиться успеха на 99,9% в моих звонках, любое предложение для достижения этого будет отличным. спасибо.

Ответы [ 6 ]

2 голосов
/ 17 июня 2009

Лучшим способом было бы расширить SoapClient и добавить повтор в методе __call.

class LocalSoapClient extends SoapClient
{

  public function __call($function_name, $arguments)
  {
    $result = false;
    $max_retries = 5;
    $retry_count = 0;

    while(! $result && $retry_count < $max_retries)
    {
      try
      {
        $result = parent::__call($function_name, $arguments);
      }
      catch(SoapFault $fault)
      {
        if($fault->faultstring != 'Could not connect to host')
        {
          throw $fault;
        }
      }
      sleep(1);
      $retry_count ++;
    }
    if($retry_count == $max_retries)
    {
      throw new SoapFault('Could not connect to host after 5 attempts');
    }
    return $result;
  }
}

затем, когда вы создаете экземпляр вашего мыльного клиента, используйте new LocalSoapClient() вместо new SoapClient()

1 голос
/ 10 июня 2009

call_user_func_array() отлично подходит для этого:

$result = call_user_func_array( array($this, $method), $args );

Первый аргумент - это обратный вызов псевдотипа , а второй - массив параметров, которые будут переданы функции / методу в качестве отдельных аргументов.

В качестве дополнительного примечания вы можете рассмотреть возможность регулирования повторных попыток (например, иметь время ожидания, которое удваивается каждый раз, когда происходит сбой до установленного предела). Если соединение с хостом разорвано, возможно, нет смысла повторять попытку как можно быстрее.

0 голосов
/ 29 июня 2009

Вот мое окончательное решение, которое я использую в производстве.

    protected function retry_till_success($method, $args) {
    /*
    *   -1 : unrecoverable error
    *    0 : recoverable error
    *    1 : success
    */
    $success = 0;
    $tries = 0;

    do {
        $tries++;
        $success = call_user_func_array( array($this, $method), $args );
        if ($success===0) {
            usleep(self::DELAY_MS);
        }
    } while ($success===0 && $tries < self::MAX_RETRIES);

    if ($tries >= self::MAX_RETRIES)
        return false;

    return true;
}
0 голосов
/ 10 июня 2009

$this->getCreatives не будет работать, потому что в PHP функции не являются гражданами базового класса. Вы можете использовать call_user_func[_array] или создать фабрику для задач и представлять каждую задачу как объект, который реализует интерфейс (т.е. iRepeatableTask). Таким образом, вы можете позвонить

try
{    
    $task->repeatUntilSuccess()
} catch (SoapFault $e) {...}

и преимущество в том, что эти объекты легко сохранять / восстанавливать в БД для последующего выполнения (например, с помощью cronjob и т. Д.).

0 голосов
/ 10 июня 2009

Я не совсем уверен, что вы имеете в виду, но вот как call_user_func (_array) () работает:

call_user_func($method, $arg); //call global function named $method like this: $method($arg)
call_user_func(array($this, $method), $arg); call class method on this class like this: $this->$method($arg);
//lets presume args is an array: $args = array(1, 2);
call_user_func_array($method, $args); //calls global function named $method like this: $method($args[0], $args[1]);
call_user_func_array(array($this, $method), $args); //calls class method like this: $this->$method($args[0], $args[1]);

Также см. Документацию для call_user_func:
http://nl3.php.net/manual/en/function.call-user-func.php
и для call_user_func_array:
http://nl3.php.net/manual/en/function.call-user-func-array.php

0 голосов
/ 10 июня 2009
private function retry_till_success($method, $args) {

...

$this->$method($args[0], $args[1]);

}

Вы также можете использовать ReflectionClass / ReflectionMethod и вызывать InvokeArgs () для переменного числа аргументов

http://nz.php.net/oop5.reflection

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...