需要运行方法或停止当前方法

时间:2014-02-19 05:46:42

标签: php oop controller

我正在寻找一种方法来要求方法(b)在另一个方法(a)中运行?我不能使用构造因为我想在方法(a)中设置函数的参数。如果不执行所需的方法(b),我也不希望运行方法(a)。

示例:

class baseController {
 protected function _require($blah) {
   # Required code
 }
}

class controller extends baseController {
 public function allmethods() {
    $this->_require('blah')
    # CODE
 }
 public function fail() {
    # CODE WITHOUT _require() NOT RUN
 }
}

我知道我可以在所需的方法(b)中设置变量,然后在方法(a)中检查变量是否为真,但这需要我将检查输入到每个方法(a)中。我想知道默认是否有办法实现它,所以我不必在每个方法中插入代码(a)检查是否运行了_require()。

3 个答案:

答案 0 :(得分:1)

从技术上讲,它不能以你所描述的方式完成,但你可以将任何控制器包装到代理对象/装饰器中,如下所示:

class ControllerWrapper
{
    private $controller;

    public function __construct(baseController $controller)
    {
        $this->controller = $controller;
    }

    public function __call($method, array $arguments)
    {
        $this->controller->_require('blah');
        return call_user_func_array([$this->controller, $method], $arguments);
    }
}

$wrapper = new ControllerWrapper($controller);
$wrapper->allmethods();

然后专门使用这个包装器来做所有事情;它将确保调用_require()方法。

这种方法有两个缺点:

  1. 您无法控制传递_require()
  2. 的参数
  3. 您将无法获得某些编辑将提供的任何代码完成优势。
  4. 我想最好的方法是在没有调用_require()的情况下抛出异常。

答案 1 :(得分:0)

也许类似于“模板方法”模式。

使用接口方法创建一个基础。

然后基类中的实现将调用实现的派生类

version:class baseController {
  protected function _require($blah) {
   # Required code
  }
  public function oneOfAllMethods() {
    $this->_require($blah)
    $this->_oneOfAllMethods()
  }
  function _oneOfAllMethods() {
    $this->fail()
  }
  public function fail() {
    #some code for failure 
  }

}

class controller extends baseController {
  public function _allmethods() {
     #already called $this->_require('blah')
     # CODE
  }

}

这样你可以在派生类代码之前或之后调用require()方法。 顺便说一下,我不懂PHP,为语法错误道歉

答案 2 :(得分:0)

所以我无法找到我想要的确切解决方案,但我这样做的方式可能会在将来帮助其他人。

有关详细信息,我希望这样做的主要原因是应用可以通过设置访问ID(将我的脚本称为$page)来确定用户是否有权访问该页面。虽然我可以根据动作名称设置访问级别,但它会根据不同的模块,控制器等创建大量的冗余和冲突。

我是如何改变我的路由器而不是直接调用动作,我将其设置为通过执行函数调用动作。

<强>路由器

try {
   $controller = new $controllerName;
   $controller->execute($actionName);
}
catch (Exception $e) {
   ...
}

然后在我的baseController(由每个控制器扩展)中,我添加了execute()和checkAccess,它只会根据用户是否具有访问权限返回true或false。这是指在访问级别上查询数据库的另一个类(Access)。

<强> baseController

final public function execute($action) {
    $actionMethod = '_action'.$action;
    $accessMethod = '_access'.$action;
    if (!method_exists($this, $actionMethod)) {
        throw new Exception('Action method not defined.');
    }
    if (!method_exists($this, $accessMethod)) {
        throw new Exception('Access method not defined.');
    }
    $page = $this->$accessMethod();
    if (strtolower($page) != 'public' and !Access::check($page)) {
        throw new Exception("Access denied for action $action.");
    }
    $this->$actionMethod();
}

final public function checkAccess($action) {
    $actionMethod = '_action'.$action;
    $accessMethod = '_access'.$action;
    if (!method_exists($this, $actionMethod) or !method_exists($this, $accessMethod)) {
        return false;
    }

    $page = $this->$accessMethod;
    if (strtolower($page) == 'public' or Access::check($page)) {
        return true;
    }
    else {
        return false;
    }
}

最后,现在我可以在控制器中设置两个不同的受保护方法(操作/访问)。如果缺少任何一个,execute()将抛出相关的异常并停止运行。

示例控制器

class Controller extends baseController {
  protected function _accessTest() {
    return 'access_page_id';
  }
  protected function _actionTest() {
    ...code here...
  }
}