2009-06-10 26 views
1

我的第一個問題在這裏。PHP OO重試邏輯實現並通過動態方法和參數

的問題是類似這樣的:PHP: Retrying a query a set number of times or until success

嘗試,直到在面向對象的方式取得成功。 這裏例如我想要做的事:

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%的成功率在我的電話,任何建議,以實現這一點將是偉大的。 謝謝。

回答

2

最好的方法是擴展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; 
    } 
} 

那麼當你實例化你的SOAP客戶端使用new LocalSoapClient()代替new SoapClient()

0
private function retry_till_success($method, $args) { 

... 

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

}

你也可以使用ReflectionClass/ReflectionMethod並調用InvokeArgs()爲參數的個數可變數量

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

+0

謝謝,但這應該是泛型數字的參數 – stac 2009-06-10 09:17:21

1

call_user_func_array()這是偉大的:

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

第一個參數我是回調pseudo-type,第二個是一個參數數組,它將作爲單獨的參數傳遞給函數/方法。作爲一個便箋,您可能想要考慮限制您的重試次數(例如,每次失敗達到設定限制時都會有一個雙倍的睡眠時間)。如果與主機的連接斷開,則可能沒有太多重試的時間。

0

我不太清楚你的意思,可是這是多麼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

$this->getCreatives將不起作用,因爲在PHP函數中不是基類公民。您可以使用call_user_func[_array]或爲任務創建工廠,並將每個任務表示爲實現接口的對象(即iRepeatableTask)。因此,你可以撥打

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

和優勢是那些objecs是易於保存/ DB中恢復後執行(即的cronjob等)。

0

下面是我在生產中使用我的最終解決方案。

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; 
}