In this guide I want to show you an easiest way to display block cart module inside block top menu module in your shop. This tutorial is based on my free module to create hooks in PrestaShop called "hooks manager". Addon is absolutely free and you can download it now from linked page. Do it, because addon is necessary in this tutorial. We will create new hook and we will put module there.
Create new hook
As I already mentioned - we have to create new hook and put it inside block top menu. So, please use hooks manager module and create hook named "displayInsideMenu". Exactly as I show on the picture below. You can also watch videoguide related to module usage .
new hook creation process with hook manager free module
Executing new hook inside block top menu (top horizontal menu)
So we already created a new hook. Now we have to execute it (display all modules associated with this hook). In this case, we need to add tiny shortcode to top horizontal menu module template file. Please open template file named blocktopmenu.tpl. It is located inside module directory and if exists: in theme /modules/ directory (if it exists - edit this one) /themes/your- theme/modules/blocktopmenu/blocktopmenu.tpl. To execute hook we have to use "exec" function from Hook class:
{Hook::exec('hook_name_here')}
we have to replace "hook_name_here" with our new hook name: displayInsideMenu
{Hook::exec('displayInsideMenu')}
Put this shortcode to <ul> element, exactly as i show below. Code below is a code from blocktopmenu.tpl file. You can see where I added Hook::exec function because this line is highlighted (you can grab code and replate your blocktopmenu.tpl file)
{if $MENU != ''} <!-- Menu --> <div id="block_top_menu" class="sf-contener clearfix col-lg-12"> <div class="cat-title">{l s="Menu" mod="blocktopmenu"}</div> <ul class="sf-menu clearfix menu-content"> {$MENU} {if $MENU_SEARCH} <li class="sf-search noBack" style="float:right"> <form id="searchbox" action="{$link->getPageLink('search')|escape:'html':'UTF-8'}" method="get"> <p> <input type="hidden" name="controller" value="search" /> <input type="hidden" value="position" name="orderby"/> <input type="hidden" value="desc" name="orderway"/> <input type="text" name="search_query" value="{if isset($smarty.get.search_query)}{$smarty.get.search_query|escape:'html':'UTF-8'}{/if}" /> </p> </form> </li> {/if} {Hook::exec('displayInsideMenu')} </ul> </div> <!--/ Menu --> {/if}
Okay, so block top menu module is ready to execute modules associated with our new hook displayInsideMenu. Now it's time to associate our cart module with this hook.
Associate block cart module with new hook
To associate block cart module with our new hook we have to alter main module .php file to add there support of displayInsideMenu hook. So please open main module .php file: /modules/blockcart/blockcart.php. At the very end of the file, right before the last closing bracket please add code of the function to support our new hook:
public function hookdisplayInsideMenu($params){ if (Configuration::get('PS_CATALOG_MODE')) return; $this->smarty->assign(array( 'order_page' => (strpos($_SERVER['PHP_SELF'], 'order') !== false), 'blockcart_top' => (isset($params['blockcart_top']) && $params['blockcart_top']) ? true : false, )); $this->assignContentVars($params); return $this->display(__FILE__, 'blockcart-menu.tpl'); }
Save changes to this file. Now our block cart module is ready to support hook that we created inside block top menu module. As you probably noticed block cart module uses new template file "blockcart-menu.tpl". Create it inside module directory with these contents:
<li class="pull-right"> <!-- MODULE Block cart --> {if isset($blockcart_top) && $blockcart_top} <div class="clearfix{if $PS_CATALOG_MODE} header_user_catalog{/if}"> {/if} <div class="shopping_cart" style="padding-top:0px; "> <a href="{$link->getPageLink($order_process, true)|escape:'html':'UTF-8'}" title="{l s='View my shopping cart' mod='blockcart'}" rel="nofollow" style="padding-top:14px; padding-bottom:20px;"> <b>{l s='Cart' mod='blockcart'}</b> <span class="ajax_cart_quantity{if $cart_qties == 0} unvisible{/if}">{$cart_qties}</span> <span class="ajax_cart_product_txt{if $cart_qties != 1} unvisible{/if}">{l s='Product' mod='blockcart'}</span> <span class="ajax_cart_product_txt_s{if $cart_qties < 2} unvisible{/if}">{l s='Products' mod='blockcart'}</span> <span class="ajax_cart_total{if $cart_qties == 0} unvisible{/if}"> {if $cart_qties > 0} {if $priceDisplay == 1} {assign var='blockcart_cart_flag' value='Cart::BOTH_WITHOUT_SHIPPING'|constant} {convertPrice price=$cart->getOrderTotal(false, $blockcart_cart_flag)} {else} {assign var='blockcart_cart_flag' value='Cart::BOTH_WITHOUT_SHIPPING'|constant} {convertPrice price=$cart->getOrderTotal(true, $blockcart_cart_flag)} {/if} {/if} </span> <span class="ajax_cart_no_product{if $cart_qties > 0} unvisible{/if}">{l s='(empty)' mod='blockcart'}</span> </a> {if !$PS_CATALOG_MODE} <div class="cart_block block exclusive" style="margin-top:0px; top:0px;"> <div class="block_content"> <!-- block list of products --> <div class="cart_block_list{if isset($blockcart_top) && !$blockcart_top}{if isset($colapseExpandStatus) && $colapseExpandStatus eq 'expanded' || !$ajax_allowed || !isset($colapseExpandStatus)} expanded{else} collapsed unvisible{/if}{/if}"> {if $products} <dl class="products"> {foreach from=$products item='product' name='myLoop'} {assign var='productId' value=$product.id_product} {assign var='productAttributeId' value=$product.id_product_attribute} <dt data-id="cart_block_product_{$product.id_product|intval}_{if $product.id_product_attribute}{$product.id_product_attribute|intval}{else}0{/if}_{if $product.id_address_delivery}{$product.id_address_delivery|intval}{else}0{/if}" class="{if $smarty.foreach.myLoop.first}first_item{elseif $smarty.foreach.myLoop.last}last_item{else}item{/if}"> <a class="cart-images" href="{$link->getProductLink($product.id_product, $product.link_rewrite, $product.category)|escape:'html':'UTF-8'}" title="{$product.name|escape:'html':'UTF-8'}"><img src="{$link->getImageLink($product.link_rewrite, $product.id_image, 'cart_default')}" alt="{$product.name|escape:'html':'UTF-8'}" /></a> <div class="cart-info"> <div class="product-name"> <span class="quantity-formated"><span class="quantity">{$product.cart_quantity}</span> x </span><a class="cart_block_product_name" href="{$link->getProductLink($product, $product.link_rewrite, $product.category, null, null, $product.id_shop, $product.id_product_attribute)|escape:'html':'UTF-8'}" title="{$product.name|escape:'html':'UTF-8'}">{$product.name|truncate:13:'...'|escape:'html':'UTF-8'}</a> </div> {if isset($product.attributes_small)} <div class="product-atributes"> <a href="{$link->getProductLink($product, $product.link_rewrite, $product.category, null, null, $product.id_shop, $product.id_product_attribute)|escape:'html':'UTF-8'}" title="{l s='Product detail' mod='blockcart'}">{$product.attributes_small}</a> </div> {/if} <span class="price"> {if !isset($product.is_gift) || !$product.is_gift} {if $priceDisplay == $smarty.const.PS_TAX_EXC}{displayWtPrice p="`$product.total`"}{else}{displayWtPrice p="`$product.total_wt`"}{/if} <div class="hookDisplayProductPriceBlock-price"> {hook h="displayProductPriceBlock" product=$product type="price" from="blockcart"} </div> {else} {l s='Free!' mod='blockcart'} {/if} </span> </div> <span class="remove_link"> {if !isset($customizedDatas.$productId.$productAttributeId) && (!isset($product.is_gift) || !$product.is_gift)} <a class="ajax_cart_block_remove_link" href="{$link->getPageLink('cart', true, NULL, "delete=1&id_product={$product.id_product|intval}&ipa={$product.id_product_attribute|intval}&id_address_delivery={$product.id_address_delivery|intval}&token={$static_token}")|escape:'html':'UTF-8'}" rel="nofollow" title="{l s='remove this product from my cart' mod='blockcart'}"> </a> {/if} </span> </dt> {if isset($product.attributes_small)} <dd data-id="cart_block_combination_of_{$product.id_product|intval}{if $product.id_product_attribute}_{$product.id_product_attribute|intval}{/if}_{$product.id_address_delivery|intval}" class="{if $smarty.foreach.myLoop.first}first_item{elseif $smarty.foreach.myLoop.last}last_item{else}item{/if}"> {/if} <!-- Customizable datas --> {if isset($customizedDatas.$productId.$productAttributeId[$product.id_address_delivery])} {if !isset($product.attributes_small)} <dd data-id="cart_block_combination_of_{$product.id_product|intval}_{if $product.id_product_attribute}{$product.id_product_attribute|intval}{else}0{/if}_{if $product.id_address_delivery}{$product.id_address_delivery|intval}{else}0{/if}" class="{if $smarty.foreach.myLoop.first}first_item{elseif $smarty.foreach.myLoop.last}last_item{else}item{/if}"> {/if} <ul class="cart_block_customizations" data-id="customization_{$productId}_{$productAttributeId}"> {foreach from=$customizedDatas.$productId.$productAttributeId[$product.id_address_delivery] key='id_customization' item='customization' name='customizations'} <li name="customization"> <div data-id="deleteCustomizableProduct_{$id_customization|intval}_{$product.id_product|intval}_{$product.id_product_attribute|intval}_{$product.id_address_delivery|intval}" class="deleteCustomizableProduct"> <a class="ajax_cart_block_remove_link" href="{$link->getPageLink('cart', true, NULL, "delete=1&id_product={$product.id_product|intval}&ipa={$product.id_product_attribute|intval}&id_customization={$id_customization|intval}&token={$static_token}")|escape:'html':'UTF-8'}" rel="nofollow"> </a> </div> {if isset($customization.datas.$CUSTOMIZE_TEXTFIELD.0)} {$customization.datas.$CUSTOMIZE_TEXTFIELD.0.value|replace:"<br />":" "|truncate:28:'...'|escape:'html':'UTF-8'} {else} {l s='Customization #%d:' sprintf=$id_customization|intval mod='blockcart'} {/if} </li> {/foreach} </ul> {if !isset($product.attributes_small)}</dd>{/if} {/if} {if isset($product.attributes_small)}</dd>{/if} {/foreach} </dl> {/if} <p class="cart_block_no_products{if $products} unvisible{/if}"> {l s='No products' mod='blockcart'} </p> {if $discounts|@count > 0} <table class="vouchers{if $discounts|@count == 0} unvisible{/if}"> {foreach from=$discounts item=discount} {if $discount.value_real > 0} <tr class="bloc_cart_voucher" data-id="bloc_cart_voucher_{$discount.id_discount|intval}"> <td class="quantity">1x</td> <td class="name" title="{$discount.description}"> {$discount.name|truncate:18:'...'|escape:'html':'UTF-8'} </td> <td class="price"> -{if $priceDisplay == 1}{convertPrice price=$discount.value_tax_exc}{else}{convertPrice price=$discount.value_real}{/if} </td> <td class="delete"> {if strlen($discount.code)} <a class="delete_voucher" href="{$link->getPageLink("$order_process", true)}?deleteDiscount={$discount.id_discount|intval}" title="{l s='Delete' mod='blockcart'}" rel="nofollow"> <i class="icon-remove-sign"></i> </a> {/if} </td> </tr> {/if} {/foreach} </table> {/if} {assign var='free_ship' value=count($cart->getDeliveryAddressesWithoutCarriers(true, $errors))} <div class="cart-prices"> <div class="cart-prices-line first-line"> <span class="price cart_block_shipping_cost ajax_cart_shipping_cost{if !($page_name == 'order-opc') && $shipping_cost_float == 0 && (!$cart_qties || $cart->isVirtualCart() || !isset($cart->id_address_delivery) || !$cart->id_address_delivery || $free_ship)} unvisible{/if}"> {if $shipping_cost_float == 0} {if !($page_name == 'order-opc') && (!isset($cart->id_address_delivery) || !$cart->id_address_delivery)}{l s='To be determined' mod='blockcart'}{else}{l s='Free shipping!' mod='blockcart'}{/if} {else} {$shipping_cost} {/if} </span> <span{if !($page_name == 'order-opc') && $shipping_cost_float == 0 && (!$cart_qties || $cart->isVirtualCart() || !isset($cart->id_address_delivery) || !$cart->id_address_delivery || $free_ship)} class="unvisible"{/if}> {l s='Shipping' mod='blockcart'} </span> </div> {if $show_wrapping} <div class="cart-prices-line"> {assign var='cart_flag' value='Cart::ONLY_WRAPPING'|constant} <span class="price cart_block_wrapping_cost"> {if $priceDisplay == 1} {convertPrice price=$cart->getOrderTotal(false, $cart_flag)}{else}{convertPrice price=$cart->getOrderTotal(true, $cart_flag)} {/if} </span> <span> {l s='Wrapping' mod='blockcart'} </span> </div> {/if} {if $show_tax && isset($tax_cost)} <div class="cart-prices-line"> <span class="price cart_block_tax_cost ajax_cart_tax_cost">{$tax_cost}</span> <span>{l s='Tax' mod='blockcart'}</span> </div> {/if} <div class="cart-prices-line last-line"> <span class="price cart_block_total ajax_block_cart_total">{$total}</span> <span>{l s='Total' mod='blockcart'}</span> </div> {if $use_taxes && $display_tax_label && $show_tax} <p> {if $priceDisplay == 0} {l s='Prices are tax included' mod='blockcart'} {elseif $priceDisplay == 1} {l s='Prices are tax excluded' mod='blockcart'} {/if} </p> {/if} </div> <p class="cart-buttons"> <a id="button_order_cart" class="btn btn-default button button-small" href="{$link->getPageLink("$order_process", true)|escape:"html":"UTF-8"}" title="{l s='Check out' mod='blockcart'}" rel="nofollow"> <span> {l s='Check out' mod='blockcart'}<i class="icon-chevron-right right"></i> </span> </a> </p> </div> </div> </div><!-- .cart_block --> {/if} </div> {if isset($blockcart_top) && $blockcart_top} </div> {/if} {counter name=active_overlay assign=active_overlay} {if !$PS_CATALOG_MODE && $active_overlay == 1} <div id="layer_cart"> <div class="clearfix"> <div class="layer_cart_product col-xs-12 col-md-6"> <span class="cross" title="{l s='Close window' mod='blockcart'}"></span> <h2> <i class="icon-check"></i>{l s='Product successfully added to your shopping cart' mod='blockcart'} </h2> <div class="product-image-container layer_cart_img"> </div> <div class="layer_cart_product_info"> <span id="layer_cart_product_title" class="product-name"></span> <span id="layer_cart_product_attributes"></span> <div> <strong class="dark">{l s='Quantity' mod='blockcart'}</strong> <span id="layer_cart_product_quantity"></span> </div> <div> <strong class="dark">{l s='Total' mod='blockcart'}</strong> <span id="layer_cart_product_price"></span> </div> </div> </div> <div class="layer_cart_cart col-xs-12 col-md-6"> <h2> <!-- Plural Case [both cases are needed because page may be updated in Javascript] --> <span class="ajax_cart_product_txt_s {if $cart_qties < 2} unvisible{/if}"> {l s='There are [1]%d[/1] items in your cart.' mod='blockcart' sprintf=[$cart_qties] tags=['<span class="ajax_cart_quantity">']} </span> <!-- Singular Case [both cases are needed because page may be updated in Javascript] --> <span class="ajax_cart_product_txt {if $cart_qties > 1} unvisible{/if}"> {l s='There is 1 item in your cart.' mod='blockcart'} </span> </h2> <div class="layer_cart_row"> <strong class="dark"> {l s='Total products' mod='blockcart'} {if $use_taxes && $display_tax_label && $show_tax} {if $priceDisplay == 1} {l s='(tax excl.)' mod='blockcart'} {else} {l s='(tax incl.)' mod='blockcart'} {/if} {/if} </strong> <span class="ajax_block_products_total"> {if $cart_qties > 0} {convertPrice price=$cart->getOrderTotal(false, Cart::ONLY_PRODUCTS)} {/if} </span> </div> {if $show_wrapping} <div class="layer_cart_row"> <strong class="dark"> {l s='Wrapping' mod='blockcart'} {if $use_taxes && $display_tax_label && $show_tax} {if $priceDisplay == 1} {l s='(tax excl.)' mod='blockcart'} {else} {l s='(tax incl.)' mod='blockcart'} {/if} {/if} </strong> <span class="price cart_block_wrapping_cost"> {if $priceDisplay == 1} {convertPrice price=$cart->getOrderTotal(false, Cart::ONLY_WRAPPING)} {else} {convertPrice price=$cart->getOrderTotal(true, Cart::ONLY_WRAPPING)} {/if} </span> </div> {/if} <div class="layer_cart_row"> <strong class="dark{if $shipping_cost_float == 0 && (!$cart_qties || $cart->isVirtualCart() || !isset($cart->id_address_delivery) || !$cart->id_address_delivery)} unvisible{/if}"> {l s='Total shipping' mod='blockcart'} {if $use_taxes && $display_tax_label && $show_tax}{if $priceDisplay == 1}{l s='(tax excl.)' mod='blockcart'}{else}{l s='(tax incl.)' mod='blockcart'}{/if}{/if} </strong> <span class="ajax_cart_shipping_cost{if $shipping_cost_float == 0 && (!$cart_qties || $cart->isVirtualCart() || !isset($cart->id_address_delivery) || !$cart->id_address_delivery)} unvisible{/if}"> {if $shipping_cost_float == 0} {if (!isset($cart->id_address_delivery) || !$cart->id_address_delivery)}{l s='To be determined' mod='blockcart'}{else}{l s='Free shipping!' mod='blockcart'}{/if} {else} {$shipping_cost} {/if} </span> </div> {if $show_tax && isset($tax_cost)} <div class="layer_cart_row"> <strong class="dark">{l s='Tax' mod='blockcart'}</strong> <span class="price cart_block_tax_cost ajax_cart_tax_cost">{$tax_cost}</span> </div> {/if} <div class="layer_cart_row"> <strong class="dark"> {l s='Total' mod='blockcart'} {if $use_taxes && $display_tax_label && $show_tax} {if $priceDisplay == 1} {l s='(tax excl.)' mod='blockcart'} {else} {l s='(tax incl.)' mod='blockcart'} {/if} {/if} </strong> <span class="ajax_block_cart_total"> {if $cart_qties > 0} {if $priceDisplay == 1} {convertPrice price=$cart->getOrderTotal(false)} {else} {convertPrice price=$cart->getOrderTotal(true)} {/if} {/if} </span> </div> <div class="button-container"> <span class="continue btn btn-default button exclusive-medium" title="{l s='Continue shopping' mod='blockcart'}"> <span> <i class="icon-chevron-left left"></i>{l s='Continue shopping' mod='blockcart'} </span> </span> <a class="btn btn-default button button-medium" href="{$link->getPageLink("$order_process", true)|escape:"html":"UTF-8"}" title="{l s='Proceed to checkout' mod='blockcart'}" rel="nofollow"> <span> {l s='Proceed to checkout' mod='blockcart'}<i class="icon-chevron-right right"></i> </span> </a> </div> </div> </div> <div class="crossseling"></div> </div> <!-- #layer_cart --> <div class="layer_cart_overlay"></div> {/if} {strip} {addJsDef CUSTOMIZE_TEXTFIELD=$CUSTOMIZE_TEXTFIELD} {addJsDef img_dir=$img_dir|escape:'quotes':'UTF-8'} {addJsDef generated_date=$smarty.now|intval} {addJsDef ajax_allowed=$ajax_allowed|boolval} {addJsDef hasDeliveryAddress=(isset($cart->id_address_delivery) && $cart->id_address_delivery)} {addJsDefL name=customizationIdMessage}{l s='Customization #' mod='blockcart' js=1}{/addJsDefL} {addJsDefL name=removingLinkText}{l s='remove this product from my cart' mod='blockcart' js=1}{/addJsDefL} {addJsDefL name=freeShippingTranslation}{l s='Free shipping!' mod='blockcart' js=1}{/addJsDefL} {addJsDefL name=freeProductTranslation}{l s='Free!' mod='blockcart' js=1}{/addJsDefL} {addJsDefL name=delete_txt}{l s='Delete' mod='blockcart' js=1}{/addJsDefL} {addJsDefL name=toBeDetermined}{l s='To be determined' mod='blockcart' js=1}{/addJsDefL} {/strip} <!-- /MODULE Block cart --> </li>
Transplanting block cart module to displayInsideMenu hook
The last step of association process is "transplanting" module to displayInsideMenu hook. In this case go to modules > positions section. Click on "anhor" button to transplant module. From transplant form please select "cart block module" and from hooks list select displayInsideMenu hook - then click on confirmation button. Module will be transplanted to new hook :-)
Transplanting process of cart block module to new hook
It's almost done :-) It's time to clean up the theme now.
Cleaning up the old cart block
To clean up theme we need to ungook the module from old position - this just means that we need to remove cart block module from displayTop hook (important: displayTop not displayHeader!). Go to modules > positions again. On the hooks list search for list of modules named "displayTop" and unhook cart block module from this section. And that's all!