【问题标题】:How to get controller method in Observer in magento?如何在 Magento 的 Observer 中获取控制器方法?
【发布时间】:2014-10-01 11:30:26
【问题描述】:

我需要 Observer 中的控制器方法

我的观察者:

public function observer()
{
//need controller action here
}

我的控制器:

public function adminAction()
    {
    //my action
    }

我的问题

  1. 这是否可以在 magento 的观察者中调用控制器方法。
  2. 如果是,请解释如何? 如果没有,那么有什么方法可以通过观察者来触发控制器动作?

【问题讨论】:

    标签: magento


    【解决方案1】:

    你可以在任何地方实例化一个控制器

    $controller = Mage::getControllerInstance(
        'The_Controller_Class',
        Mage::app()->getRequest(),
        Mage::app()->getResponse());
    

    要判断这是否是最好的方法,我需要更多地了解您的用例,但可能不是。如果您想在不重定向的情况下显示不同的页面,请查看Mage_Core_Controller_Varien_Action::_forward()

    /**
     * Throw control to different action (control and module if was specified).
     *
     * @param string $action
     * @param string|null $controller
     * @param string|null $module
     * @param array|null $params
     */
    protected function _forward($action, $controller = null, $module = null, array $params = null)
    {
        $request = $this->getRequest();
    
        $request->initForward();
    
        if (isset($params)) {
            $request->setParams($params);
        }
    
        if (isset($controller)) {
            $request->setControllerName($controller);
    
            // Module should only be reset if controller has been specified
            if (isset($module)) {
                $request->setModuleName($module);
            }
        }
    
        $request->setActionName($action)
            ->setDispatched(false);
    }
    

    不幸的是,它受到保护,因此只能在控制器内使用。但是你可以从其他任何地方做同样的事情。这里发生了什么:

    1. 原始请求(可通过Mage::app()->getRequest() 获得)已备份:$request->initForward()
    2. 请求对象随后会使用不同的控制器操作和参数进行修改。
    3. 请求的“已分派”标志设置为假。这样,在当前控制器动作完成后,前端控制器将使用现在更改的参数再次分发请求。

    如果您的观察者附加到在调度之前发生的事件,则更改请求参数就足够了。

    【讨论】:

    • $controller = Mage::getControllerInstance('index','Mbyte_Pushnotification/Adminhtml_SqliteupdateController','Pushnotification');我收到以下错误:警告:include() [function.include]: Failed opening 'Mbyte/Pushnotification/Adminhtml/SqliteupdateController.php'
    • 这是哪个 Magento 版本? getControllerInstance的第一个参数应该是实际的类名,比如Mbyte_Pushnotification_Adminhtml_SqliteupdateController,里面没有/
    • Magento 版本:1.8.0.0
    • 现在我添加了代码 $controller = Mage::getControllerInstance('Mbyte_Pushnotification_Adminhtml_Sqliteupda‌​teController','Mbyte_Pushnotification/Adminhtml_Sqliteupda‌​teController','Pushnotification');还是同样的错误:2014-10-02T06:55:03+00:00 ERR (3): Warning: include(Mbyte/Pushnotification/Adminhtml/Sqliteupda‌​teController.php) [ function.include]:无法打开流:第 93 行的 /home1/mercodec/public_html/lib/Varien/Autoload.php 中没有这样的文件或目录
    • 其他两个参数应该仍然是请求和响应,就像我的回答一样。
    【解决方案2】:

    是的,您可以监听动态事件:

    controller_action_predispatch_' . $this->getFullActionName()

    controller_action_postdispatch_' . $this->getFullActionName()

    你可以在app/code/core/Mage/Core/Controller/Varien/Action.php找到这些事件的调度

    $this->getFullActionName() 方法返回一个由routeName_controllerName_actionName 组成的字符串,因此,假设您的 routeName 是 myadminroute,您的 controllerName 是 mycontroller 并且您的操作是 admin(就像您的代码一样),您可以在事件:

    controller_action_predispatch_myadminroute_mycontroller_admin

    controller_action_postdispatch_myadminroute_mycontroller_admin

    如果您在管理区,您可以收听:

    controller_action_predispatch_adminhtml_myadminroute_mycontroller_admin

    controller_action_postdispatch_adminhtml_myadminroute_mycontroller_admin

    在您的观察者类中,您可以通过以下方式检索动作控制器:

    $observer->getControllerAction()

    示例:

    假设你在管理区:

    <config>
        ...
        <models>
            <my_model_prefix>
                <class>MyNamespace_MyModule_Model</class>
            </my_model_prefix>
        </models>
        ...
        <events>
            <controller_action_predispatch_adminhtml_myadminroute_mycontroller_admin>
                <observers>
                    <my_event_unique_tag>
                        <type>singleton</type>
                        <class>my_model_prefix/observer</class>
                        <method>myObserverMethod</method>
                    </my_event_unique_tag>
                </observers>
            </controller_action_predispatch_adminhtml_myadminroute_mycontroller_admin>
        </events>
        ...
     </config>
    

    Model/Observer.php:

    class MyNamespace_MyModule_Model_Observer
    {
        public function myObserverMethod($observer)
        {
            $controller = $observer->getControllerAction();
            // do some stuff
        }
    }
    

    【讨论】:

    • 感谢您的回复,我需要您的帮助,您能否举例说明我如何与我的观察者一起实现这一点。
    • 我已经添加了一个例子,希望这会有所帮助:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多