라우터 클래스에서 지시할 때 프런트엔드 컨트롤러 클래스를 찾을 수 없음
-
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());
이 대사는 제가 영감을 받아 추가한 것입니다. 인추의 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 문)를 제거하기 위해 너무 많은 시간을 소비했습니다...
아마도..아마도 이 게시물은 언젠가 다른 사람의 좌절감을 덜어줄 것입니다 :)