Magento 1: como substituir / reescrever uma classe de controlador de núcleo?

7

Nota : Esta é uma pergunta canônica que explica completamente como as regravações do controlador funcionam e pode ser usada como destino duplicado para perguntas mais específicas sobre "Como substituo o controlador X" ou "Por que minha reescrita não funciona".

Veja também: Procurando perguntas canônicas sobre substituições do Magento 1

Digamos que eu tenha que fazer alterações em uma classe de controlador principal em um módulo personalizado (alterar métodos ou adicionar métodos). Como faço isso passo a passo?

Raphael na Digital Pianism
fonte
1
Você não acha que já existem muitas respostas abrangentes para o Magento 1? PS você pode olhar para a minha última pergunta :)
Vishwas Bhatnagar
2
Não sei como me sinto sobre isso. (O que não é nem condenação nem admiração.)
benmarks 29/08/16
1
@VishwasBhatnagar, verifique o link na pergunta para entender completamente por que essa pergunta está sendo feita;)
Raphael no Digital Pianism
@ benmarks não hesite em contactar-me se você quiser ter uma discussão sobre isso. Talvez Fabian deva estar lá também
Raphael no Digital Pianism

Respostas:

11

Existem várias abordagens, mas vou começar como isso não é feito para esclarecer alguns equívocos comuns:

  1. É não é possível para substituir classes do controlador copiando-os para app/code/local. Isso ocorre porque as classes do controlador não são carregadas Varien_Autoload, mas os arquivos são incluídos explicitamente.
  2. Não é mais recomendado usar <rewrite><controller><to>sintaxe. Esta é uma técnica antiga e obsoleta desde o Magento 1.3 (consulte: Substituindo Controlador vs Substituindo Solicitação do Controlador de Ação )

Adicionar / substituir ações do controlador

Para adicionar ações do controlador a um controlador existente, use o seguinte em seu config.xml:

<frontend>             <--- area (adminhtml or frontend)
    <routers>
        <checkout>     <--- front name (in admin always "adminhtml")
            <args>
                <modules>
                    <stack_checkout before="Mage_Checkout">Stack_Checkout</stack_checkout>
                                                  ^                ^
                                                  |                |
                                           module to override      |
                </modules>                 (in admin always        |
            </args>                        "Mage_Adminhtml")   your module
        </checkout>
    </routers>
</frontend>

Em seguida, crie um controlador em seu módulo, como

class Stack_Checkout_OnepageController extends Mage_Core_Controller_Front_Action
{
    public function indexAction()
    {
        // here you override checkout/onepage/index
    }
    public function helloAction()
    {
        // here you create a new action checkout/onepage/hello
    }
}

Você não precisa estender a classe do controlador original porque o Magento procurará nas duas classes, na ordem definida por before="..."

Se você precisar estender a classe original porque deseja reutilizar outros métodos, precisará incluí-la (lembre-se, os controladores não são carregados automaticamente):

require_once(Mage::getModuleDir('controllers','Mage_Checkout') . DS . 'OnepageController.php');

Use observadores para modificar as ações do controlador

Se você não adicionar novas ações, uma alternativa é usar observadores para modificar o comportamento das ações existentes. Toda ação do controlador aciona um evento dinâmico "predispatch" no formulário controller_action_predispatch_$FRONTNAME_$CONTROLLER_$ACTION, por exemplocontroller_action_predispatch_checkout_onepage_index

No observador, você tem acesso à própria classe do controlador usando

$controller = $observer->getControllerAction();

Se você não deseja que o método original seja acionado, diga ao Magento para não despachar ainda mais a ação:

$controller->setFlag('', Mage_Core_Controller_Front_Action::FLAG_NO_DISPATCH, true);

Para garantir a integridade: Você também pode impedir eventos "pós-distribuição" de maneira semelhante, mas isso geralmente não é necessário (aqui está um exemplo em que é útil: XML possui conteúdo extra ):

$controller->setFlag('', Mage_Core_Controller_Front_Action::FLAG_NO_POST_DISPATCH);

Por falar nisso, você também pode adicionar um observador, controller_action_postdispatch_$FRONTNAME_$CONTROLLER_$ACTIONse desejar executar ações ou modificações adicionais da resposta após a ação original ter sido executada.

Fabian Schmengler
fonte
3

Reescrever:

Quando reescrevemos as magento Core classes em nossa classe, estamos reescrevendo.

1) Exemplo de reescrita: na reescrita, você precisa criar sua própria classe e precisa estender a classe principal e pode reescrever as funções principais do magento ou sua própria função e lógica.

No seu arquivo config.xml

<config>
<frontend>
    <routers>
        <tag>
            <args>
                <modules>
                    <inchoo_tag before="Mage_Tag">Inchoo_Tag</inchoo_tag>
                </modules>
            </args>
        </tag>
    </routers>
</frontend>

No seu arquivo de controlador

require_once(Mage::getModuleDir('controllers','Mage_Tag').DS.'TagController.php');


class Inchoo_Tag_TagController extends Mage_Tag_TagController
{
// some code
}

No Adminhtml

em yourconfig.xml deve ser

<config>
<admin>
    <routers>
        <adminhtml>
            <args>
                <modules>
                    <inchoo_tag before="Mage_Adminhtml">Inchoo_Tag_Adminhtml</inchoo_tag>
                </modules>
            </args>
        </adminhtml>
    </routers>
</admin>

e sua classe de controlador deve ser

require_once(Mage::getModuleDir('controllers','Mage_Adminhtml').DS.'TagController.php');


class Inchoo_Tag_Adminhtml_TagController extends Mage_Adminhtml_TagController
{
// some code
}

Obrigado pela equipe Inchoo.

http://inchoo.net/magento/overriding-magento-blocks-models-helpers-and-controllers/

Murtuza Zabuawala
fonte
1
Já faz um tempo, mas acho que você não pode substituir as definições de classe do controlador via pool de códigos.
benmarks 29/08/16
Ok, eu vou atualizar a minha resposta
Murtuza Zabuawala