【问题标题】:How can I tell if a Magento request is for a frontend or backend page?如何判断 Magento 请求是针对前端页面还是后端页面?
【发布时间】:2012-03-30 09:13:30
【问题描述】:

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

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

【问题讨论】:

    标签: php magento


    【解决方案1】:

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

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

    结合

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

    在商店 ID 未按预期设置的情况下充当后备(Magento 连接等)

    【讨论】:

    • @Colin 这不会抓住一切。
    【解决方案2】:

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

    我正在使用

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

    有一段时间,但事实证明某些管理页面(Magento Connect 包管理器)并非如此。出于某种原因,此页面明确将商店 ID 设置为 1,这使得 isAdmin 返回为 false。

    #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
    }
    

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

    【讨论】:

    • 嗯,这不会检查脚本是否在后端运行,但是否有管理员登录......
    • 但是为什么return (bool) Mage::getSingleton('admin/session')->getUser();不是一个好方法呢?
    • @webbiedave 如果您在后台但未登录会怎样?
    • @AlanStorm:我是一个 magento 新手,所以我真的不知道。事实上,我什至不知道这是可能的!不登录如何访问后端(我想我以为后端和管理部分是一回事)?
    • @webbiedave 在管理员登录页面上,在您登录之前。
    【解决方案3】:

    如果您能够使用观察者,则可以将其限制在“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>
    

    【讨论】:

      【解决方案4】:

      我喜欢哔哔逻辑的回答——它在观察者的上下文中是有意义的。我也喜欢 Alan 的观点,即无法知道所有上下文中的管理员状态,这是“管理员”的功能,即在应用程序和前端控制器初始化后进入的状态。

      Magento 的管理状态是从控制调度到管理操作控制器有效地创建的;见Mage_Adminhtml_Controller_Action::preDispatch()。这是触发adminhtml_controller_action_predispatch_start 事件的方法,该事件由Mage_Adminhtml_Model_Observer::bindStore() 使用,这是最初“设置”管理存储的位置。事实上,观察者配置区域(adminhtml vs frontend)“工作”是因为主要的动作控制器类 - 请参阅Mage_Core_Controller_Varien_Action::preDispatch(),特别是Mage::app()-&gt;loadArea($this-&gt;getLayout()-&gt;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:使用观察者,甚至使用相同的观察者模型,但通过指定不同的调用方法传入上下文。

      我还包含一些示例代码,使用 beeplogic 的答案中的配置作为起点。

      【讨论】:

        【解决方案5】:

        不管我错与否(但我已经测试过了),一些事件(比如controller_front_init_before)只能在全局节点内被覆盖。因此,此覆盖将影响前端和后端。

        然后是 Alan 和 Benmark 的救援解决方案,以指定您是仅在前端还是仅在后端应用观察者。

        【讨论】:

          猜你喜欢
          • 2012-08-19
          • 1970-01-01
          • 2023-03-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-02
          相关资源
          最近更新 更多