从路由器类定向时未找到前端控制器类
-
13-12-2019 - |
题
虽然我熟悉使用前端控制器进行注册,但如果不首先对控制器类的 PHP 包含进行硬编码,我似乎无法从路由器类中使用此前端控制器。 如果一切配置正确,我认为这没有必要。 我想利用这个路由器类来查看请求的 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());
我添加了这些线条,同时从中汲取灵感 Inchoo 2012 年的帖子.
最终配置如下:
等/配置.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 语句)......
或许..也许,有一天这篇文章会帮其他人省去几个小时的挫败感:)