2015-11-26 26 views
2

我寫了一個名爲Task的小型抽象類。我喜歡讓每個任務邏輯的類來擴展它。如何在PHP中完成__constructor之後自動調用方法?

在我的抽象類「任務」中,我喜歡調用每個類中定義的已定義的「execute」方法。

我試圖使用神奇的方法__call,但它不工作。

如果您在我的方法中注意到我回顯消息,它永遠不會在屏幕上打印。

這裏是我的抽象任務類

<?php 

namespace App\Modules\Surveys\Tasks; 

use App\Modules\Surveys\Tasks\Support\Traits\HtmlHelper; 

abstract class Task 
{ 
    /* 
    | 
    | This task base class provides a central location to place any logic that 
    | is shared across all of your tasks. 
    | 
    */ 

    use HtmlHelper; 


    /** 
    * checks wether a get method execute exists and calls it 
    * 
    * @param string $name 
    * @param array $args optional 
    * @return mixed 
    */ 
    public function __call($name, $args = []) 
    { 

     echo 'Attempt to execute task'; 

     if (method_exists($this, 'execute')) { 

      return call_user_func_array('execute', $args); 

     } else { 

      throw new \Exception('execute method does does not exists in your task! ' . get_class($this)); 

     } 
    } 
} 


?> 

這是一個合乎邏輯的類

<?php 

namespace App\Modules\Surveys\Tasks\Interviews; 

use App\Modules\Surveys\Tasks\Task; 

use App\Modules\Surveys\Models\SurveyInterview; 

use Exception; 


class ResumeInterview extends Task 
{ 

    protected $surveyId; 

    protected $callId; 

    protected $myInterview; 

    /** 
    * Create a new task instance. 
    * 
    * @return void 
    */ 
    public function __construct($surveyId, $callId) 
    { 

     $this->surveyId = intval($surveyId); 

     $this->callId = intval($callId); 
    } 


    /** 
    * Resume existing interview if one exists using the giving $surveyId and $callId 
    * 
    * @return void 
    */ 
    protected function execute() 
    { 
     //find the current interview if one exits 
     $myInterview = SurveyInterview::surveyAndCall($this->surveyId, $this->callId)->first(); 

     $this->setInterview($myInterview); 

     if($this->wasResumed()){ 
      //At this point existing interview was found 

      if($myInterview->status != 'Pending'){ 
       //At this point the interview is completed and should not be conducted 
       throw new Exception('This interview can not not be retaken. It\'s current status is "' . $myInterview->status . '"'); 
      } 

     } 


    } 

    /** 
    * Return the current interview 
    * 
    * @return App\Models\Survey\SurveyInterview 
    */ 
    public function getInterview() 
    { 
     return $this->myInterview; 
    } 

    /** 
    * It checks whether ot the the interview was resumed 
    * 
    * @return boolean 
    */ 
    public function wasResumed() 
    { 
     return $this->getInterview() ? true : false; 
    } 

    /** 
    * It sets the interview 
    * 
    * @param Illuminate\Support\Collection $myInterview 
    * @param void 
    */ 
    protected function setInterview($myInterview) 
    { 
     $this->myInterview = $myInterview; 
    } 
} 

我怎麼會自動調用(如果存在)的執行方法,否則拋出異常?

+0

爲什麼不在你的父類構造函數中做這個,然後在子類中做'parent :: __ construct();'? –

回答

5

我會是這樣的:

abstract class Task { 
    [...] 

    public function __construct() { 
     $this->execute(); 
    } 

    protected function execute() { 
     throw new Exception('NOT IMPLEMENTED'); 
    } 

    [...] 
} 

class ResumeInterview extends Task { 
    protected $surveyId; 
    protected $callId; 
    protected $myInterview; 

    public function __construct($surveyId, $callId) { 
     $this->surveyId = intval($surveyId); 
     $this->callId = intval($callId); 
     parent::__construct(); 
    } 

    protected function execute() { [...] } 
} 

簡單地調用基類的構造函數​​。

編輯:請注意,只有在子類實現自己的構造函數時才需要調用parent::__construct();,否則不需要。

+2

打敗我吧。我會與這個答案一起去。 – dchayka

+0

那麼爲什麼我需要這段代碼,如果我也可以在擴展類構造函數中執行$ this-> execute()?我希望避免在每個任務類中編寫$ this-> execute() –

+0

這樣,您可以在基類構造函數中添加更多的邏輯並一次調用它。 –

0

爲了避免必須在子類中調用parent::__construct,某些框架將定義一個單獨的init方法供孩子重寫,該方法將從父級調用。

abstract class Task 
{ 
    public function __construct($name, $args = []) 
    { 
     $this->init(); 
    } 
    public function init() 
    { 
     // Throwing this exception is optional and can be removed to make init optional. 
     throw new \Exception('init method must be overridden by child class.'); 
    } 
} 

class ResumeInterview extends Task 
{ 
    public function init() 
    { 
     echo "My awesome init method that does not need to use parent::!"; 
    } 
} 

要做到這一點,你將不得不在你的子類中使用__construct

+0

*我真棒的init方法,不需要使用parent ::任何東西!*只有當父類不**執行她自己的'__construct( )'或者它仍然必須調用'parent :: __ construct()' –

+0

最後,這個解決方案和我自己的完全一樣。 –

+0

@MatteoTassinari嗯,不,因爲它有不同的名字。 –

相關問題