Запрос Magento - Frontend или Backend?
Как узнать, является ли текущий запрос для бэкэнд-страницы или интерфейса? Эта проверка будет выполнена внутри наблюдателя, поэтому у меня есть доступ к объекту запроса, если это помогает.
Я считал проверку Mage::getSingleton('admin/session')->getUser()
, но я не считаю это очень надежным методом. Я надеюсь на лучшее решение.
Ответы
Ответ 1
Это одна из тех областей, где нет хорошего ответа. Сама Magento не предоставляет явный метод /API для этой информации, поэтому при любом решении вам нужно будет изучить среду и сделать выводы.
Я использовал
Mage::app()->getStore()->isAdmin()
но, оказывается, есть определенные страницы администрирования (менеджер пакетов Magento Connect), где это неверно. По какой-то причине эта страница явно устанавливает идентификатор хранилища равным 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');
}
Могут быть другие страницы с таким поведением,
Еще одна хорошая ставка - проверить свойство "area" пакета дизайна.
Это кажется менее вероятным для переопределения страницы, которая находится в админке, так как область влияет на путь к шаблонам проектирования областей администрирования и 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
}
Таким образом, когда/если вы обнаружите дыры в логике проверки администратора, вы можете исправить все в одном централизованном месте.
Ответ 2
Если вы можете использовать наблюдателя, вы можете ограничить его в области событий "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>
Ответ 3
Посмотрите методы внутри Mage/Core/Model/Store.php
, которые вы хотите использовать:
Mage::app()->getStore()->isAdmin()
В сочетании с
Mage::getDesign()->getArea() == 'adminhtml'
Сделать резервную копию, когда идентификатор магазина не установлен так, как вы ожидаете (Magento connect и т.д.)
Ответ 4
Мне нравится ответ на звуковой сигнал - это имеет смысл в контексте наблюдателей. Мне также нравится, что Алан указывает, что нет никакого способа узнать состояние администратора во всех контекстах, что является функцией "admin", являющейся состоянием, которое вводится после инициализации приложения и переднего контроллера.
Состояние администратора 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()->loadArea($this->getLayout()->getArea());
- просто обратите внимание, что объект макета имеет свою информацию о зоне, заданную в предварительной настройке adminhtml.
Независимо от того, как вы его обрезаете, поведение администратора, на котором мы полагаемся во многих контекстах - даже на таком высоком уровне, как система наблюдения за событиями, опирается на структуру управления командами.
<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: использовать наблюдателя, даже использовать одну и ту же модель наблюдателя, но передавать в контексте, указав другой метод вызова.
НТН.
edit: добавлен примерный код с использованием битовой логической конфигурации в качестве отправной точки
Ответ 5
Я ошибаюсь или нет (но я его протестировал), некоторые события (например, controller_front_init_before) могут быть перезаписаны только внутри глобального node. В результате это переопределение будет влиять как на внешний интерфейс, так и на бэкэнд.
Затем запустите решение Alan и benmark для спасения, чтобы указать, хотите ли вы применять наблюдателя только к интерфейсу или только к серверу.