如何判断当前请求是针对后端还是前端页面?此检查将在观察者内部完成,因此如果有帮助,我可以访问请求对象。

我考虑过检查 Mage::getSingleton('admin/session')->getUser() 但我不认为这是一个非常可靠的方法。我希望有一个更好的解决方案。

有帮助吗?

解决方案

这是没有好答案的领域之一。Magento本身没有为这些信息提供明确的方法/API,因此对于任何解决方案,您都需要检查环境并推断事物。

我用的是

Mage::app()->getStore()->isAdmin()

有一段时间,但事实证明有一些管理页面(Magento Connect软件包管理器),这不是真的。出于某种原因,此页面显式地将商店id设置为1,这使得 isAdmin 返回为假。

#File: app/code/core/Mage/Connect/controllers/Adminhtml/Extension/CustomController.php
public function indexAction()
{
    $this->_title($this->__('System'))
         ->_title($this->__('Magento Connect'))
         ->_title($this->__('Package Extensions'));

    Mage::app()->getStore()->setStoreId(1);
    $this->_forward('edit');
}

可能还有其他页面具有此行为,

另一个不错的选择是检查设计包的"区域"属性。

对于管理中的页面,这似乎不太可能被复盖,因为该区域会影响到管理区域设计模板和布局XML文件的路径。

无论您选择从环境中推断什么,都要创建新的Magento模块,并向其添加帮助器类

class Namespace_Modulename_Helper_Isadmin extends Mage_Core_Helper_Abstract
{
    public function isAdmin()
    {
        if(Mage::app()->getStore()->isAdmin())
        {
            return true;
        }

        if(Mage::getDesign()->getArea() == 'adminhtml')
        {
            return true;
        }

        return false;
    }
}

然后每当你需要检查你是否在管理员中,使用这个帮助器

if( Mage::helper('modulename/isadmin')->isAdmin() )
{
    //do the thing about the admin thing
}

这样,当/如果您发现管理员检查逻辑中的漏洞时,您可以在一个集中的地方纠正所有内容。

其他提示

如果您能够使用观察者,则可以将其限制在"adminhtml"事件区域。

<config>
...
  <adminhtml>
    <events>
      <core_block_abstract_prepare_layout_after>
        <observers>
          <mynamespace_mymodule_html_before>
            <type>singleton</type>
            <class>mynamespace_mymodule/observer</class>
            <method>adminPrepareLayoutBefore</method>
          </mynamespace_mymodule_html_before>
        </observers>
      </core_block_abstract_prepare_layout_after>
    </events>
  </adminhtml>
</config>

看看里面的方法 Mage/Core/Model/Store.php 你会想用:

Mage::app()->getStore()->isAdmin()

Mage::getDesign()->getArea() == 'adminhtml'

作为商店ID未按预期设置的后备(Magento connect等)。)

我喜欢beep logic的答案-在观察者的背景下是有意义的。我也喜欢Alan的观点,即没有办法知道所有上下文中的admin状态,这是"the admin"的功能,是在应用程序和前端控制器初始化后输入的状态。

Magento的管理状态是从控制调度到管理操作控制器有效地创建的;见 Mage_Adminhtml_Controller_Action::preDispatch().这是触发 adminhtml_controller_action_predispatch_start 事件,这是由消耗 Mage_Adminhtml_Model_Observer::bindStore(), ,这是管理商店最初"设置"的地方。事实上,观察者配置区域(adminhtml vs前端)"工作",因为主操作控制器类-请参阅 Mage_Core_Controller_Varien_Action::preDispatch(), ,具体来说 Mage::app()->loadArea($this->getLayout()->getArea()); -只需注意布局对象在adminhtml predispatch中设置了其区域信息。

无论你如何切片它,我们在这么多上下文中所依赖的管理行为-甚至像事件观察者系统这样高级别的东西-都依赖于命令控制结构。

<config>
  <!-- ... -->
  <adminhtml>
    <events>
      <core_block_abstract_prepare_layout_after>
        <observers>
          <mynamespace_mymodule_html_after>
            <type>singleton</type>
            <class>mynamespace_mymodule/observer</class>
            <method>adminPrepareLayoutAfter</method>
          </mynamespace_mymodule_html_after>
        </observers>
      </core_block_abstract_prepare_layout_after>
    </events>
  </adminhtml>
  <frontend>
    <events>
      <core_block_abstract_prepare_layout_after>
        <observers>
          <mynamespace_mymodule_html_after>
            <type>singleton</type>
            <class>mynamespace_mymodule/observer</class>
            <method>frontendPrepareLayoutAfter</method>
          </mynamespace_mymodule_html_after>
        </observers>
      </core_block_abstract_prepare_layout_after>
    </events>
  </frontend>
</config>

在你的观察者定义中:

class Mynamepace_Mymodule_Model_Observer
{
    public function adminPrepareLayoutAfter()
    {
        $this->_prepareLayoutAfter('admin');
    }

    public function frontendPrepareLayoutAfter()
    {
        $this->_prepareLayoutAfter('frontend');
    }

    protected function _prepareLayoutAfter($area)
    {
        switch($area){
           case 'admin':
               // do admin things
               break;

           case 'frontend':
               // do frontend things
               break;

           default:
               // i'm a moron
        }
    }
}

tl;dr:使用观察者,甚至使用相同的观察者模型,但通过指定不同的调用方法在上下文中传递。

HTH。

编辑:添加了使用beep logic的配置作为起点的示例代码

无论我是否错了(但我已经测试过),一些事件(如controller_front_init_before)只能在全局节点内部复盖。因此,此复盖将影响前端和后端。

然后来Alan和benmark的救援解决方案,以指定是否要仅在前端或仅后端应用观察者。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top