views:

2005

answers:

2

When I hit my module on this url http://localhost/xxx/index.php/TradeEnquiry I get this error

Fatal error: Call to a member function setFormAction() on a non-object in C:\wamp\www\stockdisplays\app\code\local\Stock\Tradeenquiry\controllers\IndexController.php on line 55

Line 55 is this:

 $this->getLayout()->getBlock('tradeenquiryView')
            ->setFormAction( Mage::getUrl('*/*/post') );

this is a fragment from my layout xml:

<default>
    <reference name="footer_links">
        <action method="addLink" translate="label title" module="tradeenquiry">
       <label>Trade Enquiry</label>
       <url>tradeenquiry</url>
       <title>Trade Enquiry</title>
       <prepare>true</prepare>
      </action>
    </reference>
</default>

<tradeenquiry_index_index>
    <reference name="root">
        <action method="setTemplate"><template>page/2columns-right.phtml</template></action>
        <action method="setHeaderTitle" translate="title" module="tradeenquiry"><title>Trade Enquiry</title></action>
    </reference>
    <reference name="content">
        <block type="core/template" name="tradeenquiryView" template="tradeenquiry/view.phtml"/>
    </reference>
</tradeenquiry_index_index>

I dont get what the problem is? the block is correctly named 'tradeenquiryView'. The only thing I can think of is that the layout xml is cached somehow? As I have to hit the module on /TradeEnquiry and not /tradeenquiry like I have stated in my layout xml, so its almost as if its using an older version?

+1  A: 

Like everything Magento, there's a numerous reasons this could be happening.

First, I'd avoid using a capital letter "V" when naming your blocks. Although I don't think this would cause a problem (as names are references to URIs (core/textlist, etc.) and template filepath (/path/to/template.phtml)), there's a de-facto naming convention in the layout system of lowercase/underscore names which someone, somewhere (i.e Varien) may decide is an enforced convention.

Second, have you called

$this->loadLayout();

in your controller action before the line where you attempt to set the form action? Until you do this your Layout object won't have instantiated and/or have a reference to your block objects, which means

$this->getLayout()->getBlock('...')

will always return false.

Other debugging tips. Try the following to make sure you're getting back the classes you think you should.

die(get_class($this->getLayout()->getBlock('root')));         
die(get_class($this->getLayout()));

Finally, if all that fails, go to the source of the layout object

app/code/core/Mage/Core/Model/Layout.php

And take a look at the getBlock method

public function getBlock($name)
{
    if (isset($this->_blocks[$name])) {
        return $this->_blocks[$name];
    } else {
        return false;
    }
}

and start throwing in debug statements to see if you can figure out why the system isn't returning a reference to your block. Don't forget to remove/not-check-in your debugging statements as this is core system code.

Alan Storm
Thank again for another one of your comprehensive answers. Your points about $this->loadLayout(); and the capital V, im sure are valid, but that is the way the Magento Contacts module does it?Ill debug like you say and then see what I get
Dan
I debugged getBlock and my block is not set so its returning a false. How can this be? Its set in the layout xml, is there somewhere else I need to look?
Dan
If _blocks is empty it's because you haven't called the controller's loadLayout method yet. If _blocks isn't empty but lacks a "tradeenquiryView", then that means the final "page layout" doesn't have your tradeenquiryView block in it. Can you grab the module at http://stackoverflow.com/questions/1087733/magento-my-account-layout-xml-problem/1088107#1088107and post the results of showLayout=page and showLayout=handles?
Alan Storm
A: 

Hi Allan, I have exactly the same problem.

Here is my IndexController:

   public function indexAction()
    {
        $this->loadLayout();
        $this->getLayout()->getBlock('leadsForm')
            ->setFormAction( Mage::getUrl('*/*/save') );

        $this->_initLayoutMessages('customer/session');
        $this->_initLayoutMessages('core/session');

        $this->renderLayout();
    }

And this is my leads.xml:

    <?xml version="1.0"?>
<layout version="0.1.0">
    <leads_index_index  translate="label">
        <label>Leads Form</label>
        <reference name="root">
            <action method="setTemplate"><template>page/1column.phtml</template></action>
        </reference>
        <reference name="content">
            <block type="core/template" name="leadsForm" template="leads/form.phtml" />
        </reference>
    </leads_index_index>
</layout>

When I do the debug as you suggest I got this:

die(get_class($this->getLayout()->getBlock('root'))); --> Mage_Page_Block_Html
die(get_class($this->getLayout())); --> Mage_Core_Model_Layout

So...I'm a little lost...any help? Thanks!

gaston