Pergunta

Embora eu esteja familiarizado com o registro usando um controlador front-end, não consigo utilizar esse controlador front-end da minha classe de roteador sem primeiro codificar um PHP incluído na classe do controlador. O que não acredito que seja necessário se tudo estiver configurado corretamente. Gostaria de utilizar esta classe de roteador para ver se o URL solicitado corresponde à minha extensão e, em caso afirmativo, chamar o controlador/ação apropriado.Minha configuração atual é a seguinte:

No arquivo etc/config.xml da minha extensão, registrei meu roteador e meu controlador:

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

Aqui está minha classe de roteador:

Observe o require_once declaração aqui.Estou convencido de que esta linha de código é não é necessário se minha extensão fosse configurada corretamente.Por exemplo, Mage_Cms_Controller_Router não faz tal coisa.

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

}

Meu controlador front-end:

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__;
    }

}

Obviamente ainda não terminei o desenvolvimento deste controlador.Porém o objetivo deste post não está centrado no conteúdo das ações deste controlador.É simplesmente acessar essas ações do meu roteador, sem ter que fazer especificamente uma declaração require primeiro.

O próprio controlador front-end funciona perfeitamente.Na verdade, esses caminhos de URL ecoarão os nomes dos métodos conforme esperado:

/doall_manual/manual/
/doall_manual/manual/manual/
/doall_manual/manual/page/

Além disso, minha configuração atual está funcionando.Como esperado, esses caminhos de URL também funcionam conforme o esperado:

/parts-manual/
/parts-manual/ANYTHING_HERE/
/parts-manual/ANYTHING_HERE/ANYTHING_HERE_ALSO/

E por fim,/parts-manual/ANYTHING_HERE/ANYTHING_HERE_ALSO/longer_url/ resulta na página 404 do Magento.

Algumas observações:

Meu roteador está estendendo Mage_Core_Controller_Varien_Router_Standard enquanto o roteador Mage_Cms está estendendo Mage_Core_Controller_Varien_Router_Abstract.Tentei registrar meu roteador da mesma forma que o Magento:

class DoALL_Manual_Controller_Router extends Mage_Core_Controller_Varien_Router_Abstract

Adicionei isso ao meu etc/config.xml arquivo e comentei meu registro original do roteador de 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>

Em seguida, adicionei este método ao meu roteador:

/**
 * 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);
}

Esta abordagem, embora funcione, ainda não resolve a minha questão original sobre por que eu tenho que executar uma instrução require codificada na minha classe de controlador.

Foi útil?

Solução

Bem...depois de levar quase uma hora para escrever esta questão, resolvi-a literalmente assim que terminei de escrevê-la.Então, no esforço de pelo menos não desperdiçar esta hora, resolvi postá-la para que talvez possa contribuir com algo para a comunidade.

Isso aqui foi totalmente desnecessário:

$controllerInstance = Mage::getControllerInstance('DoALL_Manual_ManualController', $request, $this->getFront()->getResponse());

$request->setDispatched(true);
$controllerInstance->dispatch($request->getActionName());

Essas linhas eu adicionei, inspirando-me em Postagem de Inchoo de 2012.

A configuração final é a seguinte:

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>

Roteador:

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

}

Controlador:

(não são necessárias alterações)

Tantas horas gastas para que eu pudesse eliminar aquela linha de código (a instrução require)...

Talvez..apenas talvez, esta postagem poupe horas de frustração para alguém algum dia :)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a magento.stackexchange
scroll top