0

I've finally reached the "rendering" phase of my second Magento module, but I'm stuck again. The module is now almost complete, it has a Controller and two blocks, one of which is called by the first (one is a dashboard block, which uses the second one to populate sub-sections).

What I need to do now it add this new dashboard to Customer Account Dashboard. I was told to use layout files, and I've read about them on Magento Design Guide. I then created the layout file and added the declaration of my block in it. However, the dashboard is not modified and my data is not displayed. If I call the extension method manually (i.e. myserver/customerstats/index) I get back the snippet of HTML that I'd like to display on Customer Account page.

At first I thought that my layout file was not loaded, but I now have the proof that it's processed correctly (at least, part of it). Here's the layout file:

<layout version="0.1.0">
    <customer_account_index translate="label">
        <label>My Custom Dashboard</label>
        <reference name="customer_account_dashboard">
            <!-- The action is processed correctly, the template is overridden -->
            <action method="setTemplate"><template>customerstats/customer/account/dashboard.phtml</template></action>
            <block type="customerstats/index" name="customerstats_dashboard" as="customerstats.dashboard" template="customerstats/customerstatsdashboard.phtml" />
        </reference>
    </customer_account_index>
</layout>

I added the setTemplate action to the layout file because one of the requirements is that the new dashboard is split in two parts vertically. This means I had to modify the original customer/account/dashboard.phtml and change the structure of the page, adding two sections that will be styled as required. I'm not sure this is the correct way of doing it, but I couldn't figure out how to add my additional in a specific part of the page, without touching the .phtml file.

I modified the new dashboard.phtml, to make sure it was loaded, and I can see the Customer Account page showing my changes when I enable the action. However, the block that should be rendered by my extension doesn't appear on the page and, based on my simple "trap" (a simple "die()", to prove the code is executed), the extension method doesn't even seem to be called.

Here's the Controller I'm trying to call from the block, with the irrelevant parts removed.

class MyCompany_CustomerStats_IndexController extends Mage_Core_Controller_Front_Action {
    // The loaded block is setting its own template in the _construct() phase
    $Block = &$this->getLayout()->createBlock('customerstats/customerstatsdashboard');

    // Some data is loaded elsewhere and passed to the Block

    $this->getResponse()->setBody(
        $Block->toHtml()
    );
}

The Controller is fired properly if I call it manually (myserver /customerstats/index) and it returns fully rendered HTML, but, as mentioned in the beginning, it doesn't seem to run when the layout file comes into play.

To summarize, here are my questions:
- Am I on the right track regarding the override of Customer Account Dashboard?
- Do I have to specify a template attribute in the layout for the extension? All the blocks I implemented load their template via code (there's a logic for choosing which one to use), and I don't see the use in having the template indicated in the xml file as well.
- Once I add a block to the XML file, do I have to alter the dashboard.phtml file to render it somewhere? I'm asking because I saw the original dashboard template, and it contains various calls to getChildHtml('alias name of a block'). This leads me to think that blocks don't have to just be "exposed" in the layout file, but also manually called in the .phtml files. However, this is a speculation, since I don't have a clear understanding of the mechanism. Note: I also tried to call getChildHtml('customerstats.dashboard) inside my new dashboard.phtml, but nothing changed.

Thanks in advance for all the answers.

Update 1 - 2012/07/28
This is the code for the Block that is not rendered.

class MyCompany_CustomerStats_Block_UserStatsDashboard extends Mage_Core_Block_Template {
    const _TEMPLATE = 'customerStats/userstatsdashboard.phtml';

    public function _construct() {
        $this->setTemplate(self::_TEMPLATE);
    }
}

Also, I made an experiment with the Controller itself. I changed it as follows:

class MyCompany_CustomerStats_IndexController extends Mage_Core_Controller_Front_Action {
    die('Controller called successfully.');
}

Here are the results: - If I call "myserver/customerstats/index" from the browser, I get the message "Controller called successfully.". - If I load the dashboard page which I modified, I can see the new layout (which means that my dashboard is loaded), but not the message. To me, this means that the Controller didn't even get called.

Content of Config.xml

<?xml version="1.0"?>
<config>
    <modules>
        <MyCompany_CustomerStats>
            <version>0.1.0</version>
        </MyCompany_CustomerStats>
    </modules>
  <global>
    <helpers>
      <CustomerStats>
        <class>MyCompany_CustomerStats_Helper</class>
      </CustomerStats>
    </helpers>
    <models>
      <CustomerStats>
        <class>MyCompany_CustomerStats_Model</class>
      </CustomerStats>
    </models>
    <blocks>
      <CustomerStats>
        <class>MyCompany_CustomerStats_Block</class>
      </CustomerStats>
    </blocks>
  </global>

  <frontend>
    <routers>
      <CustomerStats>
        <use>standard</use>
        <args>
          <module>MyCompany_CustomerStats</module>
          <frontName>userstats</frontName>
        </args>
      </CustomerStats>
    </routers>
        <layout>
        <updates>
          <CustomerStats>
                  <file>customerstats.xml</file>
                </CustomerStats>
          </updates>
        </layout>
  </frontend>
</config>

Update 2 - 2012/07/28
I made an experiment that, I admit, makes absolutely no sense to me from an MVC perspective. I changed the layout and specified block type as customerstats/userstatsdashboard. I then modified the Block class MyCompany_CustomerStats_Block_UserStatsDashboard as follows:

public function _construct() {
    echo "Block rendered.";
}

Surprisingly, now something appears in the new layout, exactly where I would expect it! But this means that the Controller hasn't been called at all, which, in turn, means there's no data available for the blocks.
This really perplexes me, I've never seen an MVC model where Views manage themselves... What's the purpose of the extension's controller, then?

4

2 回答 2

3

Your block class group is CustomerStats, but you are not using this in your layout. Block class groups are simply unique text nodes under global/blocks and in no way need to "match" any folder structure (FYI). This string matters only in that it matches the first part (before the slash) of any call to createBlock(), meaning that your layout XML should specify e.g. type="CustomerStats/whatever"

In the above example the classname which would be generated would be MyCompany_CustomerStats_Block_Whatever based on your class prefix of MyCompany_CustomerStats_Block.

于 2012-07-28T16:04:46.447 回答
1

Without taking the exceptions into account, there are two types of blocks. A core/text_list and all other types. When referencing to a core/text_list, for example the content block all added blocks are automatically rendered.

When referencing to something different than core/text_list, in your case customer/account_dashboard you need to fetch the content yourself from within the template. This can be done, like you already suggested yourself, via a getChildHtml() call.

What might be wrong, though I can't verify this with the code you provided so far, is that your own customerstats/index block type can't be found in your module or it's not extending Mage_Core_Block_Template. Or you're passing a non-existing classgroup into the createBlock factory method.

So within your module there should be something like:

    <blocks>
        <customerstats>
            <class><your_namespace>_Customerstats_Block</class>
        </customerstats>
    </blocks>

But I think you might have a handle there called customerdata instead of customerstats. Since the block you call from the controller is of type customerdata/customerstatsdashboard and that one works. Though the one in your XML which uses customerstats. If this is the case you might want to try and adjust your XML to:

<block type="customerdata/index" name="customerstats_dashboard" as="customerstats.dashboard" template="customerdata/customerstatsdashboard.phtml" />

Furthermore when working with templates your block should look like. Thus always extending the Mage_Core_Block_Template. Otherwise getChildHtml will not be available. <your_namespace>_Customerstats_Block_Index extends Mage_Core_Block_Template

Hopefully this helps you with your task, otherwise please provide feedback after you've tried this.

于 2012-07-28T09:38:58.590 回答