Magento – Load phtml layout for custom module

adminlayoutmagento-1.9module

As with many previous questions, I am unable to load my custom layout as a page. Sorry if I made some noob mistake, but as you may know, as the frustration grows, less accurate the code gets… So, besides a code analysis, I ask from you a clean explanation on what defines the layout magento will use to render a specific page. What are the conventions? Where common mistakes take place? What I did wrong? Thanks in advance for any insight on my problem!

Code:

app\etc\modules\Joaobeno_MarketplaceImporter.xml

<config>
    <modules>
        <Joaobeno_MarketplaceImporter>
            <active>true</active>
            <codePool>local</codePool>
            <depends>
                <Mage_Core />
             </depends>
        </Joaobeno_MarketplaceImporter>
    </modules>
</config>

app\design\adminhtml\default\default\layout\joaobeno_marketplaceimporter.xml

<layout>
<adminhtml_marketplaceimporter_index>
    <reference name="content">
        <block type="joaobeno_marketplaceimporter/adminhtml_marketplaceimporter_index" name="templateBlock" template="marketplaceimporter/advancedimporterbackend.phtml"/>
    </reference>
</adminhtml_marketplaceimporter_index>
</layout>

app\code\local\Joaobeno\MarketplaceImporter\etc\adminhtml.xml

<config>
    <menu>
        <joaobeno_marketplaceimporter translate="title" module="joaobeno_marketplaceimporter">
            <title>Importador</title>
            <sort_order>700</sort_order>
            <children>
                <etd translate="title" module="joaobeno_marketplaceimporter">
                    <title>Importar</title>
                    <action>adminhtml/marketplaceimporter_index</action>
                    <sort_order>0</sort_order>
                </etd>
            </children>
        </joaobeno_marketplaceimporter>
    </menu>
</config>

app\code\local\Joaobeno\MarketplaceImporter\etc\config.xml

<config>
    <modules>
        <Joaobeno_MarketplaceImporter>
            <version>1.0.0</version>
        </Joaobeno_MarketplaceImporter>
    </modules>
    <global>
        <resources>
            <joaobeno_marketplaceimporter_setup>
                <setup>
                    <module>Joaobeno_MarketplaceImporter</module>
                    <class>Joaobeno_MarketplaceImporter_Model_Resource_Setup</class>
                </setup>
            </joaobeno_marketplaceimporter_setup>
        </resources>
        <blocks>
            <joaobeno_marketplaceimporter>
                <class>Joaobeno_MarketplaceImporter_Block</class>
            </joaobeno_marketplaceimporter>
        </blocks>
        <helpers>
            <joaobeno_marketplaceimporter>
                <class>Joaobeno_MarketplaceImporter_Helper</class>
            </joaobeno_marketplaceimporter>
        </helpers>
        <models>
            <joaobeno_marketplaceimporter>
                <class>Joaobeno_MarketplaceImporter_Model</class>
                <resourceModel>joaobeno_marketplaceimporter_resource</resourceModel>
            </joaobeno_marketplaceimporter>
            <joaobeno_marketplaceimporter_resource>
                <class>Joaobeno_MarketplaceImporter_Model_Resource</class>
                <entities>
                    <etd>
                        <table>joaobeno_marketplaceimporter_etd</table>
                    </etd>
                    <etd_store>
                        <table>joaobeno_marketplaceimporter_etd_store</table>
                    </etd_store>
                </entities>
            </joaobeno_marketplaceimporter_resource>
        </models>
    </global>
    <adminhtml>
        <layout>
            <updates>
                <joaobeno_marketplaceimporter>
                    <file>joaobeno_marketplaceimporter.xml</file>
                </joaobeno_marketplaceimporter>
            </updates>
        </layout>
        <translate>
            <modules>
                <Joaobeno_MarketplaceImporter>
                    <files>
                        <default>Joaobeno_MarketplaceImporter.csv</default>
                    </files>
                </Joaobeno_MarketplaceImporter>
            </modules>
        </translate>
    </adminhtml>
    <admin>
        <routers>
            <adminhtml>
                <args>
                    <modules>
                        <Joaobeno_MarketplaceImporter before="Mage_Adminhtml">Joaobeno_MarketplaceImporter_Adminhtml</Joaobeno_MarketplaceImporter>
                    </modules>
                </args>
            </adminhtml>
        </routers>
    </admin>
</config>

UPDATE

Sorry for forgeting this!

app\code\local\Joaobeno\MarketplaceImporter\controllers\Adminhtml\Marketplaceimporter\IndexController.php

class Joaobeno_MarketplaceImporter_Adminhtml_Marketplaceimporter_IndexController extends Mage_Adminhtml_Controller_Action
{
    public function indexAction()
    {
        $this->loadLayout();
        $this->renderLayout();
    }
}

Best Answer

I assume it's a case issue. Magento Controller Class Matching would match your marketplaceimporter_index against .../Marketplaceimporter/IndexController.php

A common mistake is then to name the Directory like the module MarketplaceImporter (with a capital I).

The easiest way would be to just rename the Controller Directory. I think it's also possible to use CamelCase in the Controllers Full Action Name

should be something like this:

<layout>
<adminhtml_marketplaceImporter_index>
    <reference name="content">
        <block type="joaobeno_marketplaceimporter/adminhtml_marketplaceimporter_index" name="templateBlock" template="marketplaceimporter/advancedimporterbackend.phtml"/>
    </reference>
</adminhtml_marketplaceImporter_index>
</layout>

You can also dump the Full Action Name to use in the Layout in your Controller with $this->getFullActionName() or get the css class from the body Tag and replace the - with _

If this does not help, we might need some Controller and Block Code to help you further.

===UPDATE===

Turns out it wasn't the case issue, but the full action name was missing an _index at the end.

The Full Action Name is built from the module, that the controller belongs to, the Class Path under the controllers directory + the actual Controller Name and Action Name.

1. Module (adminhtml_marketplaceimporter_index_index):

In your case, the module beeing responsible is the adminhtml module (defined in your config.xml routers config - first tag under routers).

This is the first Part of the full action name: adminhtml_marketplaceimporter_index_index

2. Class Path or Subdirectory (adminhtml_marketplaceimporter_index_index)

The next part can be found under the Class Path, that is defined in your routers config (Joaobeno_MarketplaceImporter_Adminhtml) defined in your config.xml.

The first part identifies your Module Joaobeno_MarketplaceImporter_Adminhtml.

Since it is a controller, Magento will look for it in the controllers Subdirectory.

The _Adminhtml then identifies the Subdirectory under controllers. So now you know, that the controller lies under Joaobeno/MarketplaceImporter/controllers/Adminhtml and the class Name starts with Joaobeno_MarketplaceImporter_Adminhtml

From here, I think it is up to you how to proceed. A common practice is then to use your Module Namespace and Name as Directory Structure to not accidently overwrite other modules controllers under adminhtml. This would result in the Directory (with the case problem in Mind): Joaobeno/MarketplaceImporter/controllers/Adminhtml/Joaobeno/Marketplaceimporter

or in your case only using the module name: Joaobeno/MarketplaceImporter/controllers/Adminhtml/Marketplaceimporter

This Directory Structure defines the next part from the Full Action Name: adminhtml_marketplaceimporter_index_index

3. Controller Name and Action Name (adminhtml_marketplaceimporter_index_index)

The next Part is defined by the controller name (IndexController) adminhtml_marketplaceimporter_index_index

and the last part is defined by the action name (indexAction) adminhtml_marketplaceimporter_index_index

The layout.xml in your case should then be like this I think:

<layout>
<adminhtml_marketplaceimporter_index_index>
    <reference name="content">
        <block type="joaobeno_marketplaceimporter/adminhtml_marketplaceimporter_index" name="templateBlock" template="marketplaceimporter/advancedimporterbackend.phtml"/>
    </reference>
</adminhtml_marketplaceimporter_index_index>
</layout>