gpt4 book ai didi

php - 如何让 Phalcon 将 Action 委托(delegate)给其他 Controller ?

转载 作者:搜寻专家 更新时间:2023-10-31 20:36:19 26 4
gpt4 key购买 nike

问题

我希望能够编写类似 Controller 的类,并将它们作为供应商提供给最终应用程序。然后最终应用程序 Controller 可以实例化我的类并调用它们的操作方法。

问题是我希望自动调用它们。我必须避免在终端 Controller 中重复每个操作方法。

第一种方法

我已经试过了:

代码

class IndexController
{
protected $vendorController;

public function initialize()
{
$this->vendorController = new VendorController();
}

public function __call($name, $args)
{
call_user_func_args([$this->vendorController, $name], $args);
}
}

VendorController 类如下所示:

class VendorController 
{
public function testAction()
{
die("this is test action");
}
}

结果

但它给了我

Action 'test' was not found on handler 'index'

我假设 I've checked Phalcon 在内部做了一些检查,看起来像这样:

if (method_exists($controller, $actionName)) { // ...

这会导致未找到操作。

也许我可以以某种方式覆盖此行为?如果有任何帮助,我正在使用我自己的调度程序类,它扩展了 Phalcon 的本地调度程序。但是我尝试重写 getHandlerName() 之类的方法,但没有成功。

第二种方法

我也尝试过使用特征:

代码

trait TVendorController
{
public function testAction()
{
die("this is test action");
}
}

class IndexController
{
use TVendorController;
}

这种方法可行,但有一个主要缺陷:

缺陷

如果 IndexController 扩展了某种包含 initialize()beforeExecuteRoute() 方法的 BaseController (通常是这种情况)那么很容易忘记给他们打电话。这里的威胁是 BaseController 方法可以包含例如身份验证逻辑:

trait TVendorController
{
public function beforeExecuteRoute()
{
// silently overrides the BaseController::beforeExecuteRoute()
}

public function testAction()
{
die("this is test action");
}
}


abstract class BaseController
{
public function beforeExecuteRoute()
{
// OOPS: this is never called
$username = $this->session->get('username', null);
if (!$username) {
$this->response->redirect('index/login');
}
}
}


class IndexController extends BaseController
{
use TVendorController;
}

问题

对于第一种方法:如何告诉 Phalcon 的事件循环该操作实际存在于 Controller 中?

或者如果无法完成则:

  1. 如何编写我的供应商 Controller ?
  2. 如何将它们组合到最终应用程序 Controller 中以便自动调用操作?

最佳答案

您可以尝试添加带有 dispatch:beforeDispatch 附件的 EventManager。在 dispatch:beforeDispatch 时刻,您知道操作名称,但应该可以在检查操作是否确实存在之前点击它。

beforeDispatch 函数中,您可能需要检查传递的 Action 名称是否可在 Controller 内部调用,如果不是,您应该能够转发给 execvendorAction 的某个国王方法。

编辑:

我已经完成了这个事件的管理:

$di->setShared('dispatcher', function() {

$dispatcher = new Dispatcher();

$eventsManager = new EventsManager();

$eventsManager->attach("dispatch:beforeDispatch", function($event, $dispatcher) {

$controllerName = $dispatcher->getControllerClass();
$action = $dispatcher->getActionName();

if(!method_exists($controllerName, $action . 'Action')) {

$dispatcher->forward(array(
// not delivering 'controller' param to make it stay
// in current one
'action' => 'vendor',
'params' => array(
'name' => $action,
'params' => $dispatcher->getParams()
)
));
}
});

$dispatcher->setEventsManager($eventsManager);
return $dispatcher;
});

然后,我在 controllerBase 中添加了这样一个操作:

public function vendorAction($name, $arguments) {

var_dump(array(
'name' => $name,
'arguments' => $arguments
));

// $name .= 'Action';
if(method_exists(array($this->vendorController, $name))) {
call_user_func_args(array($this->vendorController, $name), $arguments);
} else {
// work it out
}
}

并开始工作。从 controllerBase 扩展的每个 Controller 都将运行您在 vendorController 中交付的方法。您将不得不想出自己的方法来处理 notFound 异常,因为这是一个非常不标准的实现。

在 Phalcon 上使用经典路由器/调度程序/一切进行测试。

关于php - 如何让 Phalcon 将 Action 委托(delegate)给其他 Controller ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34203747/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com