ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

php-如何让Phalcon将动作委派给其他控制器?

2019-11-19 09:29:57  阅读:293  来源: 互联网

标签:event-loop phalcon php


问题

我希望能够编写类似控制器的类,并将其作为最终应用程序的供应商来提供.然后,最终应用程序控制器可以仅实例化我的类并调用其操作方法.

关键是我希望它们被自动调用.我必须避免在终端控制器中重复每种操作方法.

第一种方法

我已经试过了:

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的事件循环该动作实际上存在于控制器中?

或者,如果无法完成,则:

>如何编写我的供应商控制器?
>如何将它们组合到最终应用程序控制器中,以便自动调用操作?

解决方法:

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

在beforeDispatch函数中,您可能需要检查,是否可以在控制器中调用传递的动作名称,如果不能,则应该能够转发给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扩展的每个控制器都将在vendorController中交付的方法中运行您的方法.您将必须制定自己的方法来处理notFound异常,因为这是非常不标准的实现.

在Phalcon上使用经典路由器/调度程序/所有工具进行了测试.

标签:event-loop,phalcon,php
来源: https://codeday.me/bug/20191119/2035273.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有