如何在PHP中完成__constructor后自动调用方法?

时间:2015-11-26 17:06:09

标签: php class call magic-methods

我写了一个叫做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方法,否则抛出异常?

2 个答案:

答案 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