Load block outside Magento, and apply current template

azkotoki picture azkotoki · Jun 14, 2011 · Viewed 15.2k times · Source

I have a Magento installation which is integrated with an external website, and I want the Magento's shopping cart block to be displayed on the header of this external site.

I have achieved this with the following code:

<?php

require_once(dirname(__FILE__).'/store/app/Mage.php');

$app = Mage::app();
$session = Mage::getSingleton('core/session', array('name'=>'frontend'));

$block = $app
    ->getLayout()
    ->getBlockSingleton('checkout/cart_sidebar')
    ->setTemplate('checkout/cart/sidebar.phtml');

echo $block->toHtml();

But, I want (and believe that it's possible) a nicer approach.

I dislike the fact that I must specify the template manually via setTemplate(), which involves hard-coding template locations and repeating something that it's defined somewhere else (in the design's layout xml files). I tried loading the block via $app->getLayout()->getBlock($name) with no results (were $name represents the block's reference name, as defined in the layout xml files).

So the question is:

Is there any way to render a block outside magento (with the following requisites)?

  • I want the base layout xml and the store's design layout updates of the design changes to be loaded automatically, so i don't need to specify the template path and the block type (again) manually.
  • I want to load the block by it's reference name, so I can make use of the properties applied to it on the layout xml files.

The purpose of this question is to wrap it in a function, and render every block outside Magento the same way it's done on the Magento templates. For example:

<div id="sidebar-cart-container">
    <?php echo $this->renderMagentoBlock('cart-block-reference-id'); ?>
</div>

Thanks in advance.

Answer

Daniel Sloof picture Daniel Sloof · Jun 15, 2011

Took me a couple minutes of debugging, but it seems relatively easy.

<?php

/*
 * Initialize magento.
 */
require_once 'app/Mage.php';
Mage::init();

/*
 * Add specific layout handles to our layout and then load them.
 */
$layout = Mage::app()->getLayout();
$layout->getUpdate()
    ->addHandle('default')
    ->addHandle('some_other_handle')
    ->load();

/*
 * Generate blocks, but XML from previously loaded layout handles must be
 * loaded first.
 */
$layout->generateXml()
       ->generateBlocks();

/* 
 * Now we can simply get any block in the usual way.
 */
$cart = $layout->getBlock('cart_sidebar')->toHtml();
echo $cart;

Please note that you must manually specify which layout handles you want to load blocks from. The 'default' layout handle will contain the sidebar since it is placed there from inside checkout.xml.

But using the 'default' layout handle can come with a significant performance cost since many modules place their blocks in this handle. You may want to put all the blocks that you use on your external site in a separate layout handle and simply load that.

The choice is yours. Good luck.