Let’s compare the two versions of PrestaShop one more time and see the differences in their template structure, layouts, head, notifications, listing pages, AJAX page update and view update.
Templates in PrestaShop 1.6 vs 1.7
Template files (.tpl) is a way for Smarty to divide content, which is then displayed as a whole on a page. The template contains several dynamic elements, where our content is located. This makes it easier to design and update sites.
The template processor uses {…} to process instructions. The rest of the document is sent to the browser as it is.
You can use a template to generate HTML files, as well as XML files, text files, etc.
Any PrestaShop theme consists of such templates, responsible for their part of the output content.
PrestaShop 1.7
Template files are stored in the templates/ theme folder. For example, the default theme has its own template files in the following folder: /themes/classic/templates.
Internal folders have the following structure:
- _partials — the code located on each page of a site. (header, footer, notifications);
- catalog — Product page, product/brand/supplier listing, search result, etc.;
- checkout — Cart, delivery options, payment options, order confirmations, etc.;
- cms — all static content: contact, sitemap, CMS pages, etc.;
- customer — customer’s account and his data;
- errors — all error templates: not found, server error, forbidden, etc.;
- layouts — The theme layouts: 1, 2 or more columns, full width.
Each PrestaShop theme has the following basic templates:
- index.tpl — home page
- catalog/product.tpl — product page
- catalog/listing/product-list.tpl — product list page
- checkout/cart.tpl — cart
- checkout/checkout.tpl — checkout
PrestaShop 1.6
In PrestaShop 1.6 all .tpl files are located in the root of the theme folder:
Layouts in PrestaShop 1.6 vs 1.7
Layout is responsible for organizing the content (templates on a specific page). In other words, it’s responsible for the method of location of elements (templates) on the pages of the project.
In PrestaShop 1.7 the user is given the opportunity to change the layout of each page independently. Go to admin panel ➔ Design ➔ Theme & Logo.
Then press the Choose layouts button:
A sample of a layout file (/themes/classic/templates/layouts/layout-both-columns.tpl):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
<!doctype html> <html lang="{$language.iso_code}"> <head> {block name='head'} {include file='_partials/head.tpl'} {/block} </head> <body id="{$page.page_name}" class="{$page.body_classes|classnames}"> {block name='hook_after_body_opening_tag'} {hook h='displayAfterBodyOpeningTag'} {/block} <main> {block name='product_activation'} {include file='catalog/_partials/product-activation.tpl'} {/block} <header id="header"> {block name='header'} {include file='_partials/header.tpl'} {/block} </header> {block name='notifications'} {include file='_partials/notifications.tpl'} {/block} <section id="wrapper"> {hook h="displayWrapperTop"} <div class="container"> {block name='breadcrumb'} {include file='_partials/breadcrumb.tpl'} {/block} {block name="left_column"} <div id="left-column" class="col-xs-12 col-sm-4 col-md-3"> {if $page.page_name == 'product'} {hook h='displayLeftColumnProduct'} {else} {hook h="displayLeftColumn"} {/if} </div> {/block} {block name="content_wrapper"} <div id="content-wrapper" class="left-column right-column col-sm-4 col-md-6"> {hook h="displayContentWrapperTop"} {block name="content"} <p>Hello world! This is HTML5 Boilerplate.</p> {/block} {hook h="displayContentWrapperBottom"} </div> {/block} {block name="right_column"} <div id="right-column" class="col-xs-12 col-sm-4 col-md-3"> {if $page.page_name == 'product'} {hook h='displayRightColumnProduct'} {else} {hook h="displayRightColumn"} {/if} </div> {/block} </div> {hook h="displayWrapperBottom"} </section> <footer id="footer"> {block name="footer"} {include file="_partials/footer.tpl"} {/block} </footer> </main> {block name='javascript_bottom'} {include file="_partials/javascript.tpl" javascript=$javascript.bottom} {/block} {block name='hook_before_body_closing_tag'} {hook h='displayBeforeBodyClosingTag'} {/block} </body> </html> |
Head in PrestaShop 1.6 vs 1.7
Assets of various kinds are connected in the <HEAD> tag.
PrestaShop 1.7
The way the assets are connected has changed in PrestaShop 1.7:
- _partials/stylesheets.tpl
- _partials/javascript.tpl
This method of connection allows you to use asynchronous loading of js and inline css feature.
/themes/classic/templates/_partials/head.tpl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
{block name='head_charset'} <meta charset="utf-8"> {/block} {block name='head_ie_compatibility'} <meta http-equiv="x-ua-compatible" content="ie=edge"> {/block} {block name='head_seo'} <title>{block name='head_seo_title'}{$page.meta.title}{/block}</title> <meta name="description" content="{block name='head_seo_description'}{$page.meta.description}{/block}"> <meta name="keywords" content="{block name='head_seo_keywords'}{$page.meta.keywords}{/block}"> {if $page.meta.robots !== 'index'} <meta name="robots" content="{$page.meta.robots}"> {/if} {if $page.canonical} <link rel="canonical" href="{$page.canonical}"> {/if} {/block} {block name='head_viewport'} <meta name="viewport" content="width=device-width, initial-scale=1"> {/block} {block name='head_icons'} <link rel="icon" type="image/vnd.microsoft.icon" href="{$shop.favicon}?{$shop.favicon_update_time}"> <link rel="shortcut icon" type="image/x-icon" href="{$shop.favicon}?{$shop.favicon_update_time}"> {/block} <link href="https://fonts.googleapis.com/css?family=Oswald|Roboto" rel="stylesheet"> {block name='stylesheets'} {include file="_partials/stylesheets.tpl" stylesheets=$stylesheets} {/block} {block name='javascript_head'} {include file="_partials/javascript.tpl" javascript=$javascript.head vars=$js_custom_vars} {/block} {block name='hook_header'} {$HOOK_HEADER nofilter} {/block} {block name='hook_extra'}{/block} |
The {block name=’head_seo’} block contains the necessary information for SEO, which is easy to edit.
PrestaShop 1.6
There is no separate template containing the <head> tag In PrestaShop 1.6.
There is a common header.tpl that also contains the <body> part (/themes/default-bootstrap/header.tpl):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
<!DOCTYPE HTML> <!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"{if isset($language_code) && $language_code} lang="{$language_code|escape:'html':'UTF-8'}"{/if}><![endif]--> <!--[if IE 7]><html class="no-js lt-ie9 lt-ie8 ie7"{if isset($language_code) && $language_code} lang="{$language_code|escape:'html':'UTF-8'}"{/if}><![endif]--> <!--[if IE 8]><html class="no-js lt-ie9 ie8"{if isset($language_code) && $language_code} lang="{$language_code|escape:'html':'UTF-8'}"{/if}><![endif]--> <!--[if gt IE 8]> <html class="no-js ie9"{if isset($language_code) && $language_code} lang="{$language_code|escape:'html':'UTF-8'}"{/if}><![endif]--> <html{if isset($language_code) && $language_code} lang="{$language_code|escape:'html':'UTF-8'}"{/if}> <head> <meta charset="utf-8" /> <title>{$meta_title|escape:'html':'UTF-8'}</title> {if isset($meta_description) AND $meta_description} <meta name="description" content="{$meta_description|escape:'html':'UTF-8'}" /> {/if} {if isset($meta_keywords) AND $meta_keywords} <meta name="keywords" content="{$meta_keywords|escape:'html':'UTF-8'}" /> {/if} <meta name="generator" content="PrestaShop" /> <meta name="robots" content="{if isset($nobots)}no{/if}index,{if isset($nofollow) && $nofollow}no{/if}follow" /> <meta name="viewport" content="width=device-width, minimum-scale=0.25, maximum-scale=1.6, initial-scale=1.0" /> <meta name="apple-mobile-web-app-capable" content="yes" /> <link rel="icon" type="image/vnd.microsoft.icon" href="{$favicon_url}?{$img_update_time}" /> <link rel="shortcut icon" type="image/x-icon" href="{$favicon_url}?{$img_update_time}" /> {if isset($css_files)} {foreach from=$css_files key=css_uri item=media} {if $css_uri == 'lteIE9'} <!--[if lte IE 9]> {foreach from=$css_files[$css_uri] key=css_uriie9 item=mediaie9} <link rel="stylesheet" href="{$css_uriie9|escape:'html':'UTF-8'}" type="text/css" media="{$mediaie9|escape:'html':'UTF-8'}" /> {/foreach} <![endif]--> {else} <link rel="stylesheet" href="{$css_uri|escape:'html':'UTF-8'}" type="text/css" media="{$media|escape:'html':'UTF-8'}" /> {/if} {/foreach} {/if} {if isset($js_defer) && !$js_defer && isset($js_files) && isset($js_def)} {$js_def} {foreach from=$js_files item=js_uri} <script type="text/javascript" src="{$js_uri|escape:'html':'UTF-8'}"></script> {/foreach} {/if} {$HOOK_HEADER} <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Open+Sans:300,600&subset=latin,latin-ext" type="text/css" media="all" /> <!--[if IE 8]> <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script> <![endif]--> </head> <body{if isset($page_name)} id="{$page_name|escape:'html':'UTF-8'}"{/if} class="{if isset($page_name)}{$page_name|escape:'html':'UTF-8'}{/if}{if isset($body_classes) && $body_classes|@count} {implode value=$body_classes separator=' '}{/if}{if $hide_left_column} hide-left-column{else} show-left-column{/if}{if $hide_right_column} hide-right-column{else} show-right-column{/if}{if isset($content_only) && $content_only} content_only{/if} lang_{$lang_iso}"> {if !isset($content_only) || !$content_only} {if isset($restricted_country_mode) && $restricted_country_mode} <div id="restricted-country"> <p>{l s='You cannot place a new order from your country.'}{if isset($geolocation_country) && $geolocation_country} <span class="bold">{$geolocation_country|escape:'html':'UTF-8'}</span>{/if}</p> </div> {/if} <div id="page"> <div class="header-container"> <header id="header"> {capture name='displayBanner'}{hook h='displayBanner'}{/capture} {if $smarty.capture.displayBanner} <div class="banner"> <div class="container"> <div class="row"> {$smarty.capture.displayBanner} </div> </div> </div> {/if} {capture name='displayNav'}{hook h='displayNav'}{/capture} {if $smarty.capture.displayNav} <div class="nav"> <div class="container"> <div class="row"> <nav>{$smarty.capture.displayNav}</nav> </div> </div> </div> {/if} <div> <div class="container"> <div class="row"> <div id="header_logo"> <a href="{if isset($force_ssl) && $force_ssl}{$base_dir_ssl}{else}{$base_dir}{/if}" title="{$shop_name|escape:'html':'UTF-8'}"> <img class="logo img-responsive" src="{$logo_url}" alt="{$shop_name|escape:'html':'UTF-8'}"{if isset($logo_image_width) && $logo_image_width} width="{$logo_image_width}"{/if}{if isset($logo_image_height) && $logo_image_height} height="{$logo_image_height}"{/if}/> </a> </div> {if isset($HOOK_TOP)}{$HOOK_TOP}{/if} </div> </div> </div> </header> </div> <div class="columns-container"> <div id="columns" class="container"> {if $page_name !='index' && $page_name !='pagenotfound'} {include file="$tpl_dir./breadcrumb.tpl"} {/if} <div id="slider_row" class="row"> {capture name='displayTopColumn'}{hook h='displayTopColumn'}{/capture} {if $smarty.capture.displayTopColumn} <div id="top_column" class="center_column col-xs-12 col-sm-12">{$smarty.capture.displayTopColumn}</div> {/if} </div> <div class="row"> {if isset($left_column_size) && !empty($left_column_size)} <div id="left_column" class="column col-xs-12 col-sm-{$left_column_size|intval}">{$HOOK_LEFT_COLUMN}</div> {/if} {if isset($left_column_size) && isset($right_column_size)}{assign var='cols' value=(12 - $left_column_size - $right_column_size)}{else}{assign var='cols' value=12}{/if} <div id="center_column" class="center_column col-xs-12 col-sm-{$cols|intval}"> {/if} |
Notifications in PrestaShop 1.7
Notifications appeared in PrestaShop 1.7. This means that a client can now receive notifications from PrestaShop (e.g., notification of errors and successes). The theme can also send messages when certain events occur.
Messages are sent from the controller and are not hardcoded in the template files. This means that all messages are also translated into your specific theme language.
Types of messages:
- success — an action was performed and everything went well;
- error — something went wrong;
- warning — important information merchants should know about;
- info — “just so you know”.
To display messages on the page you need, just place the block
1 2 3 |
{block name='notifications'} {include file='_partials/notifications.tpl'} {/block} |
into the necessary template (for CMS pages it will be /themes/classic/templates/cms/page.tpl).
In the Starter Theme the default message output block is located in /templates/checkout/checkout.tpl, /templates/customer/page.tpl and /templates/layouts/layout-both-columns.tpl.
Listing pages
In PrestaShop 1.7 Listing pages contain the following templates:
They expand the catalog page without duplicating the code.
AJAX page update
The product list is updated every time the client filters products or uses the search string.
In view of the fact that PrestaShop 1.7 does not have a place for duplicating the code (No presentation code duplication), now the page is not completely rebuilt by javascript. Instead, the core generates the sub template part and returns it to the client. And javascript is only used to place the content of HTML placeholders.
Each ajax request generates the following templates:
- catalog/_partials/products-top.tpl
- catalog/_partials/products.tpl
- catalog/_partials/products-bottom.tpl
Update the view
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import $ from 'jquery'; import prestashop from 'prestashop'; import 'velocity-animate'; $(document).ready(() => { prestashop.on('updateProductList', (data) => { updateProductListDOM(data); }); } function updateProductListDOM (data) { $('#search_filters').replaceWith(data.rendered_facets); $('#js-active-search-filters').replaceWith(data.rendered_active_filters); $('#js-product-list-top').replaceWith(data.rendered_products_top); $('#js-product-list').replaceWith(data.rendered_products); $('#js-product-list-bottom').replaceWith(data.rendered_products_bottom); } |
Thank you for your time, I really hope this article was helpful. If you still have any questions concerning the differences between the two PrestaShop versions, feel free to leave them in the comment section below.
Hi Mon
please, contact BelVG support team at [email protected], as we need more details to help you with this issue.
How to solve prestashop validator dont like the nofilter smarty tag? I always get invalid module if nofilter added in themes tpl