我正在寻找一种方法来要求方法(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()。
答案 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()
方法。
这种方法有两个缺点:
_require()
。我想最好的方法是在没有调用_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...
}
}