我写了一个叫做Task的小抽象类。我喜欢让每个任务逻辑课程扩展它。
在我的抽象课程中,#34;任务"我喜欢调用已使用的已定义方法"执行"这是在每个班级中定义的。
我尝试使用魔术方法__call
,但它无效。
如果你注意到我的方法,我会回复一条永远不会在屏幕上打印的信息。
这是我的抽象Task类
<?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;
}
}
如果存在execute方法,我将如何自动调用execute方法,否则抛出异常?
答案 0 :(得分: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() { [...] }
}
只需在基类构造函数中调用execute()
。
编辑:请注意,只有在子类实现自己的构造函数时才需要调用parent::__construct();
,否则不需要。
答案 1 :(得分: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
。