代码之家  ›  专栏  ›  技术社区  ›  Devon Bessemer

要求运行方法,否则停止当前方法

  •  1
  • Devon Bessemer  · 技术社区  · 12 年前

    我正在寻找一种方法来要求在另一个方法(a)内部运行方法(b)?我不能使用construct,因为我希望函数集的参数位于方法(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 回复  |  直到 12 年前
        1
  •  1
  •   JaÍ¢ck    12 年前

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

    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. 你不会有一些编辑器所能提供的任何代码完成的优点。

    我想最好的方法是,如果 _require() 还没有打电话。

        2
  •  0
  •   Trimtab    12 年前

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

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

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

    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,对语法错误表示歉意

        3
  •  0
  •   Devon Bessemer    12 年前

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

    有关更多信息,我希望这样做的主要原因是,应用程序可以通过设置访问id(将我的脚本称为 $page ). 虽然我可以根据动作名称设置访问级别,但它会根据不同的模块、控制器等创建大量冗余和冲突。

    我的做法是将路由器更改为直接调用操作,而是将其设置为通过执行函数调用操作。

    路由器

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

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

    基本控制器

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