The noItems.phtml
template is rendered by the same block as the normal cart.phtml
template, depending on the number of items in the cart.
But it can contain a child checkout_cart_empty_widget
, which is only rendered on the noItems.phtml
cart. It does not exist in the default theme and is an empty container in the default rwd theme (used to attach widgets to it).
If you are using the rwd theme or a theme that is based on the rwd theme, you can add additional blocks to it:
<checkout_cart_index>
<reference="checkout.cart.empty.widget">
<block>whatever</block>
</reference>
</checkout_cart_index>
If not, you can add it, the same way as it's done in the rwd theme:
<checkout_cart_index>
<reference name="checkout.cart">
<block type="core/text_list" name="checkout.cart.empty.widget" as="checkout_cart_empty_widget" translate="label">
<label>Empty Shopping Cart Content Before</label>
</block>
</reference>
</checkout_cart_index>
Add block below "No items" message:
This block is rendered before the "You have no items in your shopping cart." message.
If you want to add something below this message, there is another child, called shopping.cart.table.after
, which is not created anywhere in the default themes as far as I can see, but it is also rendered in cart.phtml
of the rwd theme (not the default theme), so if you want to use this and be compatible with different themes, better create a custom product block that is only displayed if the cart is empty:
protected function _toHtml()
{
if (Mage::getSingleton('checkout/session')->getQuote()->getItemsCount() == 0) {
return parent::_toHtml();
} else {
return '';
}
}
The layout XML should be like this, to add the referenced but non-existing container block and add yours as a child:
<checkout_cart_index>
<reference name="checkout.cart">
<block type="core/text_list" name="shopping.cart.table.after" as="shopping.cart.table.after" translate="label">
<label>Shopping Cart Content After</label>
<block>whatever</block>
</block>
</reference>
</checkout_cart_index>
What works well for me to react on cart changes is a combination of these events:
- checkout_cart_save_after
- customer_login
- customer_logout
- checkout_onepage_controller_success_action
However, if I remove all items from the cart, all three events only fire once with the old number of items in the cart (for example, if I had 1 item in the cart and delete it, the event fires once with 1 item in the model, not 0).
You are probably looking at the wrong data. When items are removed from the cart, the objects get a deleted
flag but stay in the collection. If you use $cart->getItems()
or $cart->getItemsCollection()
these deleted items are included. Use $cart->getQuote()->getAllItems()
or $cart->getQuote()->getAllVisibleItems()
instead.
I explained the difference between these methods in: How to get all items in cart currently?
Best Answer
Ad your block normally, and wrap your display html in a conditional, checking for cart items.
This will work,
without having to rewrite any core blocks, or even creating your own block.
Your phtml block could then just be core template block, unless you need more cart logic in your template, then you should extend the core cart abstract block from your own block (
Mage_Checkout_Block_Cart_Abstract
) which will give you access to all the core cart methods.Then just add your block to the xml, and it will only output it's code if there are items.
Depending on what your intended display is, you can add your block as a child of these core block lists, then you don't need to change the base
cart.phtml
file to echo out your block