views:

1789

answers:

1

Context: I'm trying to include Adminhtml blocks in the frontend of the site to replace some of the user account blocks. The first thing I'm trying to do is simply display the block on the correct page. I can replace the entire page by setting the Body of the response inside the controller, but I'm having a hard time including the block in the layout xml file and then calling it within the template.

This block's default template is adminhtml/default/default/widget/grid.phtml. So I have placed widget/grid.phtml and widget/grid/ folder (needed by widget/grid.phtml) inside of the frontend theme.

I'm using community edition v1.3.2.2

Why would I be able to create an adminhtml/sales_order_grid from Mage_Sales_OrderController using createBlock:

$this->getResponse()->setBody($this->getLayout()->createBlock('adminhtml/sales_order_grid')->toHtml());

But not from a frontend layout, using a declaration

<sales_order_history>
    <reference name="content">
        <block type="adminhtml/sales_order_grid" name="orders_widget"/>
    </reference>
</sales_order_history>

within app/design/frontend/default/default/layout/sales.xml

The latter produces an error without a stack trace:

Fatal error: Call to a member function toHtml() on a non-object in app/code/core/Mage/Core/Model/Layout.php on line 526

That line is the function getOutput() that Alan refers to below. The data in callback[0] is blank. As far as I can tell, it's null. When output to a log, it's blank. get_class(callback[0]) returns nothing discernable as well.

As far as I can tell, no blocks are rendered. There is nothing shown in the browser except the error message. In the log, the only output from the getOutput() method within app/code/core/Mage/Core/Model/Layout.php is the one where it breaks - no block name in callback[0].

However, I do know that _prepareCollection on the sales_order_grid block is being called.

Update: It turns out that I can get the block to render by adding it to the layout file. The call that throws the error is in app/code/core/Mage/Sales/controllers/OrderController.php in public function historyAction(). The call to $this->renderLayout() is what causes the problem. Evidently, I can't have both the grid block and the history template rendered in the same action. I'm not sure why though.

Thanks for any guidance!

A: 

More details about the other customizations you've done to get yourself to this point might help people troubleshoot your problem. When I tried your "create the block programmatically" code I got the following error.

Warning: include(/path/to/magento1point4.dev/app/design/frontend/base/default/template/widget/grid.phtml) [function.include]: failed to open stream: No such file or directory  in /path/to/magento1point4.dev/app/code/core/Mage/Core/Block/Template.php on line 189

I added a simple phtml template to the above location and was able to insert the block via a layout file succfully after that

    <reference name="content">
        <block type="adminhtml/sales_order_grid" name="orders_widget"/>
    </reference>

So I suspect something you've done along the way already is tripping things up.

Also, a Magento version would help things. Line 526 of the current version of community edition is a comment.

All that said my best guess is things are failing in the getOutput method of the Layout class. I'd add some logging to the function on your dev server to see what Magento is trying to do/instantiate when it bails on you.

public function getOutput()
{
    $out = '';
    if (!empty($this->_output)) {
        foreach ($this->_output as $callback) {
            Mage:Log('Trying to get the block ' . $callback[0] . ' and call its ' . $callback[1] . 'method');
            $out .= $this->getBlock($callback[0])->$callback[1]();
        }
    }

    return $out;
}
Alan Storm
Thanks Alan. Yes I forgot the step of including a template file in the correct location. I'm doing that as well.I'm using community edition v1.3.2.2 and you are correct, Magento was bailing on the getOutput() method. Callback[0] is not an object. I'm not sure why this is - the adminhtml/sales_order_grid is being mapped to the correct class. Perhaps it depends on another class that isn't loaded yet?
N. B.
Were you placing the sales_order_grid block in the sales_order_history element?
N. B.
This block's template is adminhtml/default/default/widget/grid.phtml.Currently, there is no call to setTemplate inside the block, which is fine.However, I see a different behavior when I assign a different template to the block in \_\_construct() that is *not* adminhtml/default/default/widget/grid.phtml.Does grid.phtml respond differently than most templates. Instead of calling getHtml() on the template, perhaps the callback[1] method should be getGridHtml()?
N. B.
No, that doesn't make much sense... because the "programmatic method" calls toHtml() directly after calling createBlock. Ugh.
N. B.
1. It's better around here to update your original question that to use to comments. It flows better and doesn't hide the info from other people 2. What IS in callback[0]? 3. What blocks are being rendered before the failure?
Alan Storm
Thanks for the etiquette tips Alan - much appreciated.
N. B.