Класс интерфейсного контроллера не найден при перенаправлении из класса маршрутизатора
-
13-12-2019 - |
Вопрос
Хотя я знаком с регистрацией с использованием интерфейсного контроллера, я, похоже, не могу использовать этот интерфейсный контроллер из моего класса router без предварительного жесткого кодирования PHP include класса controller. Что, я думаю, не должно быть необходимым, если все настроено правильно. Я хотел бы использовать этот класс маршрутизатора, чтобы увидеть, соответствует ли запрошенный URL-адрес моему расширению, и если да, то вызвать соответствующий контроллер/действие.Моя текущая настройка выглядит следующим образом:
В файле моего расширения etc/config.xml Я зарегистрировал как свой маршрутизатор, так и контроллер:
<frontend>
<routers>
<doall_manual>
<use>standard</use>
<args>
<module>DoALL_Manual</module>
<frontName>doall_manual</frontName>
</args>
</doall_manual>
</routers>
</frontend>
<default>
<web>
<routers>
<doall_manual>
<area>frontend</area>
<class>DoALL_Manual_Controller_Router</class>
</doall_manual>
</routers>
</web>
</default>
Вот мой класс маршрутизатора:
Обратите внимание на require_once
заявление здесь.Я убежден, что эта строка кода является в этом нет необходимости если бы мой добавочный номер был настроен правильно.Например, Mage_Cms_Controller_Router ничего подобного не делает.
class DoALL_Manual_Controller_Router extends Mage_Core_Controller_Varien_Router_Standard
{
public function match(Zend_Controller_Request_Http $request)
{
// checking before even try to find out that current module
// should use this router
if (!$this->_beforeModuleMatch()) {
return false;
}
$path = explode('/', trim($request->getPathInfo(), '/'));
if ($path[0] != 'parts-manual') {
return false;
}
$request
->setModuleName('doall_manual')
->setControllerName('manual');
switch (count($path)) {
case 1:
$request->setActionName('index');
break;
case 2:
$request->setActionName('manual');
break;
case 3:
$request->setActionName('page');
break;
default:
$request->setActionName('noroute');
break;
}
// TODO: This line shouldn't be needed, but I'm unsure as to why it is not detecting the controller's location on it's own.
require_once 'DoALL'.DS.'Manual'.DS.'controllers'.DS.'ManualController.php';
$controllerInstance = Mage::getControllerInstance('DoALL_Manual_ManualController', $request, $this->getFront()->getResponse());
// dispatch action
$request->setDispatched(true);
$controllerInstance->dispatch($request->getActionName());
return true;
}
}
Мой интерфейсный контроллер:
class DoALL_Manual_ManualController extends Mage_Core_Controller_Front_Action
{
/**
* Display all manuals
*/
public function indexAction()
{
echo __METHOD__;
}
/**
* Display a manual's index
*/
public function manualAction()
{
echo __METHOD__;
}
/**
* Display the parts from a manual's page.
*/
public function pageAction()
{
echo __METHOD__;
}
}
Очевидно, я еще не закончил разработку для этого контроллера.Однако суть этого поста не сосредоточена вокруг содержания действий этого контроллера.Это просто доступ к этим действиям с моего маршрутизатора, без необходимости сначала специально выполнять для него инструкцию require.
Сам интерфейсный контроллер работает просто отлично.Эти URL-пути фактически будут отображать имена методов, как и ожидалось:
/doall_manual/manual/
/doall_manual/manual/manual/
/doall_manual/manual/page/
Кроме того, моя текущая конфигурация работает.Как я и ожидал, эти URL-пути также работают должным образом:
/parts-manual/
/parts-manual/ANYTHING_HERE/
/parts-manual/ANYTHING_HERE/ANYTHING_HERE_ALSO/
И, наконец,,
/parts-manual/ANYTHING_HERE/ANYTHING_HERE_ALSO/longer_url/
результаты на странице Magento 404.
Некоторые наблюдения:
Мой маршрутизатор расширяется Mage_Core_Controller_Varien_Router_Standard
принимая во внимание, что маршрутизатор Mage_Cms расширяет Mage_Core_Controller_Varien_Router_Abstract
.Я попытался зарегистрировать свой маршрутизатор таким же образом, как это сделал Magento:
class DoALL_Manual_Controller_Router extends Mage_Core_Controller_Varien_Router_Abstract
Добавил это к моему etc/config.xml
файл и закомментировал мою первоначальную регистрацию маршрутизатора из default/web/routers
:
<global>
<events>
<controller_front_init_routers>
<observers>
<doall_manual>
<class>DoALL_Manual_Controller_Router</class>
<method>initControllerRouters</method>
</doall_manual>
</observers>
</controller_front_init_routers>
</events>
<global>
Затем добавил этим методом к моему маршрутизатору:
/**
* Initialize Controller Router
*
* @param Varien_Event_Observer $observer
*/
public function initControllerRouters($observer)
{
/* @var $front Mage_Core_Controller_Varien_Front */
$front = $observer->getEvent()->getFront();
$front->addRouter('doall_manual', $this);
}
Этот подход, хотя и работает, все равно не решает мой первоначальный вопрос относительно почему я должен выполнять жестко запрограммированный оператор require в моем классе контроллера.
Решение
Хорошо...потратив почти час на то, чтобы записать этот вопрос, я решил его буквально сразу после того, как закончил его писать.Поэтому, стремясь, по крайней мере, не потратить этот час впустую, я решил опубликовать это, чтобы, возможно, это могло внести какой-то вклад в сообщество.
Это прямо здесь было совершенно не нужно:
$controllerInstance = Mage::getControllerInstance('DoALL_Manual_ManualController', $request, $this->getFront()->getResponse());
$request->setDispatched(true);
$controllerInstance->dispatch($request->getActionName());
Эти строки я добавил, черпая вдохновение из Пост Инчу от 2012 года.
Окончательная конфигурация выглядит следующим образом:
etc/config.xml
<frontend>
<routers>
<doall_manual>
<use>standard</use>
<args>
<module>DoALL_Manual</module>
<frontName>doall_manual</frontName>
</args>
</doall_manual>
</routers>
</frontend>
<default>
<web>
<routers>
<doall_manual>
<area>frontend</area>
<class>DoALL_Manual_Controller_Router</class>
</doall_manual>
</routers>
</web>
</default>
Маршрутизатор:
class DoALL_Manual_Controller_Router extends Mage_Core_Controller_Varien_Router_Standard
{
public function match(Zend_Controller_Request_Http $request)
{
// checking before even try to find out that current module
// should use this router
if (!$this->_beforeModuleMatch()) {
return false;
}
$path = explode('/', trim($request->getPathInfo(), '/'));
if ($path[0] != 'parts-manual') {
return false;
}
$request
->setModuleName('doall_manual')
->setControllerName('manual');
switch (count($path)) {
case 1:
$request->setActionName('index');
break;
case 2:
$request->setActionName('manual');
break;
case 3:
$request->setActionName('page');
break;
default:
$request->setActionName('noroute');
break;
}
return true;
}
}
Контроллер:
(никаких изменений не требуется)
Так много часов было потрачено на то, чтобы я мог исключить эту одну строку кода (оператор require)...
Может быть..просто, может быть, этот пост когда-нибудь избавит кого-то еще от многих часов разочарования :)