Advertisement
Other

PrestaShop Theming Explained

by

Prestashop is arguably the #1 open-source e-Commerce solution on the web. It offers countless features, add-ons, and themes, but its lack of good documentation has given newcomers the perception that it's unapproachable. In this article, I'll walk you through the process of building your own custom theme, as well as creating and customizing Prestashop modules.

Prestashop runs on PHP and mySQL, and relies on the Smarty engine for its "Templates" (pages). Don't worry, if you're not familiar with Smarty. You basically use it to create pages with placeholder sections, and Prestashop fills in the info when the page loads. It's easy to transition to, if you've used something like Handlebars or Underscore templates.

I'm going to assume that you have already downloaded and installed Prestashop. If not, you can download the latest version; they have an instructional video you can watch to learn how to set it up.

Prestashop Website

Registering Your Theme

Your site should look something like the following image, if you set up Prestashop with the default settings.

The process of building your own theme begins with creating a folder. In your file browser of choice, navigate to the root Prestashop directory and you'll find a folder, called themes. Inside the themes folder, create a new directory with the name of your theme. I'm going to call mine, "Demo."

If you add a picture of your template to this folder and name it preview.jpg, Prestashop should automatically find and add your template to the back-end. If it doesn't, or you prefer to add the picture later, you can manually add the theme. To do this, go to the Themes option under the Preferences menu, and click Add New at the top. Once completed, you will see your theme in the center of the page. Enable it by simply clicking on it and pressing the Save button.

Add your logo(s) while you're here; you can find this option at the bottom of the page. You may need to increase the file upload limit in Prestashop (or maybe even PHP's config file) if you have a very large image.


Crash Course in Prestashop

Smarty is a template engine for PHP, facilitating the separation of presentation from application logic.

As I mentioned earlier, Prestashop uses Smarty for generating the pages; so, all the template files have a .tpl extension. There are many pages you must create in order to have a complete theme; take a moment and view the file list.

Ultimately, your theme's functionality determines which pages you should implement. These page are based on the files in the controllers folder, and you can override the default controllers or add your own custom controllers to fit your theme. But that's beyond the scope of this article. Among the controllers in controllers\front directory are two template files that automatically load: header.tpl and footer.tpl.

The major content of your site will be loaded by modules with the help of "Hooks".

There are two types of hooks in Prestashop: action and display hooks. These both function the same way, but they differ in purpose. A hook basically gives the user a means to attach custom code to an outside source. In the case of an action hook, any code attached to the hook runs when the hook is called. For example, Prestashop comes with a default hook called actionProductAdd that runs when adding a product. So you could attach a module to this hook if you wanted to send an email newsletter every time a new product is added.

A display hook is very similar, but instead of connecting a function to an event, you connect a function to a specific place on the template. In other words, Prestashop will call your module by a specific point (e.g. right sidebar), and anything returned is placed into the page. You can view all the currently registered hooks by going to the Modules > Positions page in the back admin.

Personally, I find it best to start with a standard HTML theme. This isn't a requirement, but I highly recommend it for a number of reasons:

  • It allows you to immediately see which hooks you need and how to divide your content.
  • It gives you a clear direction of which template files you have to create, as well as giving you an idea of what will be static content and what should be a module. It also allows you to add preview.jpg file right away.

The following image is a picture of my example HTML template:

And here you can see how I will split it up into Prestashop hooks:


Creating the Template Partials

Now let's create the header.tpl file in your themes directory, and fill it with your themes header. This includes the doctype, area, and everything in the body that you want displayed on all pages. Here is an example header.tpl file:

<!DOCTYPE HTML>
<html>
  <head>
    <title>Prestashop Site</title>
    <link rel="stylesheet" type="text/css" href="{$css_dir}bootstrap.min.css">

    {if isset($css_files)}
      {foreach from=$css_files key=css_uri item=media}
        <link rel="stylesheet" type="text/css" href="{$css_uri}">
      {/foreach}
    {/if}

    {if isset($js_files)}
      {foreach from=$js_files item=js_uri}
        <script src="{$js_uri}"></script>
      {/foreach}
    {/if}
  </head>
  
  <body>
    <div id="head">
      <div id="menu">
        {$HOOK_TOP} 
      </div>
      <div id="banner">
        <img src="http://nettuts.s3.amazonaws.com/2169_prestashop/{$logo_url}" alt="Header Image">
      </div>
    </div>

There are a few things to point out in this code. I preprended the CSS file name with {$css_dir}. This is a Smarty variable that points to a folder, called css inside your theme's directory, where all you CSS files should go.

The next line uses Smarty's foreach loop to add all the CSS files of the enabled modules. It's worth noting that, if you create a CSS file called global.css in the css directory, the loop automatically adds that file to the page.

A few lines later, another foreach loop processes the JavaScript files in the js directory and adds them to the page. In the last section, I open the body element and define a hook for the menu module. Lastly, I finish off by displaying the site's logo.

Unless you're a Prestashop veteran, you're probably wondering where I'm coming up with these variables. As I said earlier, unfortunately Prestashop's documentation is lacking, but they do provide a debugging tool that you can launch by adding {debug} to any of the template files. When you open the corresponding page in your browser, you will get a pop-up containing a list of all variables for that specific template. This allows you to quickly (using ctrl/cmd-F dramatically helps) identify what variables are defined, as well as their values.

Now let's create the footer.tpl template. I'm going to keep this simple and just close the <body/> and <html/> elements, but feel free to add anything you want to display on the bottom of every page. This can include anything from hooks to custom JavaScript; there are no limits to what you could put here.

The last file I want to implement is the index.tpl file. This is the "home page" file that displays when a user accesses the root of your site. In the default Prestashop theme, the sidebars are loaded in the header.tpl file, and the actual index template only contains a call to the displayHome hook. This is fine if you want the sidebars to be on all pages, but again, I would like to stress that hooks are implemented at your own convenience. You don't have to implement any hook, and you can add your own custom hooks if you need more than the standard functionality.

When creating your index page, you have to decide which parts are static and which parts should be dynamically loaded through modules. I removed the main menu from the header because that is something I wanted to control with a module. So I placed a hook where I wanted the menu and I can create a module that attaches to this hook. You can load multiple items with the same hook. There is no reason to add multiple hooks together, and you can manage the order of a hook's modules in the back-end under Modules > Positions.

Localization

The last Prestashop-specific feature you should consider is Prestashop's localization tools. Prestashop allows you to easily translate your site into multiple languages by using a Smarty function, named l. You use it by replacing a standard string with the l function, passing the string as a parameter. Here is an example of an <h1/> element, both with and without translation:

{* Without Translation Tool *}
<h1>Subscribe to us!</h1>

{* With Translation Tool *}
<h1>{l s='Subscribe to us!'}</h1>

Even if you don't currently plan on translating your site, it's a small change that allows you to easily translate your pages if you later decide to do so. Once you make these changes to your templates, you can go to the Localization > Translations page in the back-end and click on the nationality you want to translate to.

Adding non-default languages is simple, and I cover it in the second section on the page (aptly named "Add/Update a Language").

Another benefit to using Prestashop's localization is the list of the phrases Prestashop gives you. Instead of going through your entire site, you can simply hand the list of phrases to a native speaker of your desired language and quickly input the values, while never touching your theme.

Now enter your home page's specific HTML to the index.tpl, and be sure to supply the hooks you want to use. Remember to use the {debug} Smarty function, if you need to see the variables are available to your template.

Now you can open a browser and navigate to your sites root. Mine looks like this:

It may not look like much, but you have built your template's outer shell. If your template looks like a mess of objects, it's probably because you have a lot of modules installed. By default, Prestashop enables many modules; I recommend going to the modules page and uninstalling all modules. Don't worry about losing them because you can reinstall them by clicking the install button next to the desired module.

When creating a Prestashop theme, you will notice that modules are responsible for approximately 90% of the content. There are modules that display the products, modules for the shopping cart, etc. A major part of being a Prestashop themer includes, at the very least, a working knowledge on how to customize the look of modules.


Modules

Modules in Prestashop are not the same as Wordpress widgets.

Modules in Prestashop are not the same as Wordpress widgets; Prestashop's modules can only be attached to hooks that the module creator specifies. For example, if you create a module that displays a "subscribe to newsletter" block and you set it up to go in either of the sidebars, you cannot then place it in the footer area.

This may seem cumbersome, but there is a very good reason for this: when you create a module, you provide a separate function for each of the hooks you want to use. For example, if a menu module can behave differently based upon its location in the template.

This gives you a lot of room to customize a module.

This practice makes a lot more sense if you consider other kind of hooks: action hooks. You obviously don't want the function that executes when you add a new product to execute when a user buys a product from you. The same applies to display hooks; each hook has its own function, letting you do whatever you want with it.

When building a theme, there are two ways you can go about adding modules. The first option is to create your own module. This is the more tedious option, but you do get a lot more control in the final product. On the other hand, there are over 2000 modules in the official modules catalog (and even more on third-party sites). Chances are good you can find something that matches your needs.

Your second option is to install a ready-made module; Prestashop gives you the option of customizing its appearance by overriding the template files. This is the better option, if you don't really want to start coding your own module, and it allows you to focus on the graphical side. I'm going to cover both options; so let's start with the first one.


Creating your own Module

We'll build a module that displays a configurable number of products on the home page. This is loosely based on the stock module, but my module will go a little more into Prestashop's underlying classes to hopefully give you a more in-depth look at the process.

First, create a folder in the modules directory, and then create a PHP file inside of it with the same name as the folder. When you open the modules folder, you will see a naming convention, where all the modules that solely display content start with the word "block". This, of course, is not a requirement, but it makes sense. I'll name my folder blockdisplayproducts, and, within it, I'll create the PHP file with the same name.

Open up the PHP file and define the modules class:

<?php

if (!defined('_PS_VERSION_'))
exit;

class BlockDisplayProducts extends Module
{
	public function __construct()
	{
		$this->name = 'blockdisplayproducts';
		$this->tab = 'front_office_features';
		$this->version = 1.0;
		$this->author = 'Gabriel Manricks';
		$this->need_instance = 0;

		parent::__construct();

		$this->displayName = $this->l('Display Products Module');
		$this->description = $this->l('Displays a configurable amount of products for the home page.');
	}

}

Prestashop modules are object-oriented; therefore, you have to create a class for your module. The name of your class should be the camel-cased version of your folder's name.

At the top of the file, you can see an if statement. This ensures that the file isn't loaded directly through the browser. Next, your class either has to directly subclass the Module class or subclass a decedent of the Module class.

Inside the constructor, we setup the module's properties. Prestashop uses this information to display in the back-end:

  • name is a unique "code name", and it's not the actual name shown in the back-end.
  • tab tells Prestashop the module's category. You can find a complete list of categories by opening the Controllers\Admin\AdminModuleController.php file.
  • author, name and version are self-explanitory.
  • needs_instance tells Prestashop to create an instance of your variable when accessing the modules page. This is usually not required, but if your module needs to show a message or log something when the modules page is active, then you should change this to a 1.

The last two lines setup the actual display name and description for your module, and they use the same localization method in order to allow translating them to different languages. These two lines have to go after the parent's initialization as per Prestashop's preferred order used by their official modules.

The next step is to override the install method. This is where we can specify the hooks we need, as well as the default options for our module. If any of the settings fail, then the installation will fail.

This module is intended for the home page, so I'll connect it to the home hook. We also want to add a CSS file to the header, meaning we'll need to add the header hook as well. If you go to the back-end under the Modules > Positions page, you can find the hooks' technical names (which is what we will specify here).

Right after the __construct() function, add the following:

public function install()
	{
			if (parent::install() == false || $this->registerHook('displayHome') == false || $this->registerHook('displayHeader') == false || Configuration::updateValue('DP_Number_of_Products', 6) == false)
					return false;
			return true;
	}

This adds the two hooks and sets the default number of products to six. You should name the property something unique so that other modules don't interfere with your values. A simple approach adds your module's name or initials to the beginning of the name.

You can now install your module in the modules page, and it should successfully install if everything is set up correctly. Go to the positions page, and it will display as registered under the the two hooks.

Implementing hooks is quite simple; create a public function with the word "hook" followed by the name of the hook. Let's start with the header hook. We just want it to add a CSS file to our theme. Here is the complete function:

public function hookdisplayHeader($params)
	{
		$this->context->controller->addCSS(($this->_path).'blockdisplayproducts.css', 'all');
	}

Create that CSS file in your themes directory, and your template should load it in the header.

The next hook is a bit more complicated. It should retrieve a certain number of products from the database and load them into a template file. The function to retrieve the products doesn't return the products' images or links, so we have to call a few different functions and 'build' an array of products. Here is the complete function:

public function hookdisplayHome($params)
	{
		$languageId = (int)($params['cookie']->id_lang);
		$numberOfProducts = (int)(Configuration::get("DP_Number_of_Products"));
		$productsData = Product::getProducts($languageId, 0, $numberOfProducts, "id_product", "ASC");
		if (!$productsData)
			return "error";
			
		$products = array();
		$link = new Link(null, "http://");
		
		foreach($productsData as $product){
			$tmp = Product::getCover($product['id_product']);
			array_push($products, array(
				'name' => $product['name'],
				'author' => $product['manufacturer_name'],
				'desc' => $product['description_short'],
				'price' => $product['price'],
				'link' => $link->getProductLink(new Product($product['id_product'])),
				'image' => $link->getImageLink($product['link_rewrite'], $tmp['id_image'])
			));
			
		}
		$this->smarty->assign(array(
			'products' => $products
		));

		return $this->display(__FILE__, 'blockdisplayproducts.tpl');
	}

It begins by getting the number of products to display and the user's language id. We then make a call to get the assigned number of products starting from the first product registered. After that, we make sure that there were no problems getting the products exiting if there was. The next block is the part I mentioned earlier, which builds up an array with all the properties we will need when displaying the item. This includes the picture and the link which were not returned with the rest of the product data. The last section adds the products array to Smarty and loads the template file of your choosing. I named the template file and the CSS files with the same name as the module, but this is not a requirement; you can name it whatever you wish.

If you open your site right now, you will only see a message, noting "No template found for module blockdisplayproducts." So let's create the template file inside our module's directory, naming it the same as you just specified in the hook function. This part really depends on your specific themes layout, but here is my template file:

{if $products !== false}
	<div id="home_products_title"><h1>{l s='OUR BOOKS' mod='blockdisplayproducts'}</h1></div>
	{foreach from=$products item=product name=productLoop}
		<div class="home_products_book">
			<div class="home_products_picture"><img src="http://nettuts.s3.amazonaws.com/2169_prestashop/{$product.image}" alt="{$product.name|strip_tags|escape:html:'UTF-8'}" /></div>
			<div class="home_products_author">{$product.author|upper|strip_tags|escape:html:'UTF-8'}</div>
			<div class="home_products_info">
				<div class="home_products_title">{$product.name|strip_tags|escape:html:'UTF-8'}</div>
				<div class="home_products_description">{$product.desc}</div>
				<div class="home_products_price">${$product.price|string_format:"%.2f"}</div>
				<div class="home_products_openButton"><a href="{$product.link}" class="btn btn-inverse">{l s='View' mod='blockdisplayproducts'}</a></div>
			</div>
		</div>
	{/foreach}
{/if}

Since Prestashop uses Smarty templates, you have a number of helper functions that you can use when displaying your data. We start off with an if function to make sure that the products array is okay. If it is, we go into a for loop, generating the specified HTML for each one. We are using Smarty's built in helper functions to strip HTML tags and covert the authors name to uppercase, and we are using another method to format the price to the desired number of decimal places. To see a full list of modifiers, see here.

Also, notice that, when translating strings here, you have to enter your module's name. This is because the translation is not tied to a theme, but to the module itself. On the other hand, the l function is template specific; so, in order for it to find your translation file, it requires the module's name.

You can now view your site in the browser; if you've added any products, they should be displayed on the home page now.

Now, our module is fully functional, but there is no way to adjust the number of products returned. To do this, we need to add a function, called getContents. If your module has this function, then Prestashop will automatically add a configure button on the "modules" page. Anything returned by this function will be displayed on the config page. To begin, add the function to the module's class and fill it with the following:

public function getContent(){
		
		
		$html  = '<div style="width:400px; margin:auto">';
		$html .= '	<h2>' . $this->displayName . ' Settings</h2>';
		$html .= '	<form action="'. Tools::safeOutput($_SERVER['REQUEST_URI']). '" method="post"><fieldset>';
		$html .= '		' . $this->l('Number of Products to Display') . ': <input type="number" name="numProds" value="' . (int)(Configuration::get('DP_Number_of_Products')) . '" />';
		$html .= ' 		<input type="submit" value="' . $this->l('Save') . '" />';
		$html .= '	</fieldset></form>';
		$html .= '</div>';
		
		return $html;
	}

This function simply builds up the HTML necessary to display a form with a number box and save button. Again, I'm using the $this->l() method so that you can translate the module into other languages in the future, should you need to do so. I've used a number field in the HTML form, but be careful, if you are making a commercial module. It's still not supported by all browsers. That said, if it's for your own personal use, then feel free!

The only other thing that might seem cryptic is the Tools::safeOutput() function that we are calling on the URL. I'm honestly not 100% sure how crucial this call is, but what it's doing is it's striping all HTML tags and converting the necessary characters to html entities.

Next, go to the modules page and click the configure button on your module. You will be greeted with the form we just made.

You can adjust the number and press save, but we haven't written in the saving functionality yet, so it will keep resetting to 6 (the value that is already saved).

Back in the function, add the following code to the beginning of the function:

if (Tools::isSubmit('numProds')){
  Configuration::updateValue('DP_Number_of_Products', (int)(Tools::getValue('numProds')));
}

This checks to see if the value was submitted - i.e., if the value numProds exists as a $_GET or $_POST variable. We then update the property where we stored the value. The method Tools::getValue accepts the name of a form field and optionally a second string of what to return if the form field was not found; it then returns a formatted string with the value that was submitted. It's important to put this before you generate the HTML form; otherwise, the form will contain the old values as apposed to the updated ones.

With that final bit of code, we've completed the module. The only other thing you should do is add a 16x16 GIF icon to your modules folder.

We are now ready to move on to the next option for integrating modules with your theme.


Overriding Existing Modules

The second option is to use an existing module and re-theme it according to your likings. This option is considerably simpler as you only need to re-create the ".tpl" file(s) from the module.

My example theme is still missing a top navigation menu, so let's customize that module. To get started, enable/install the module in the 'modules' page, called 'Top horizontal menu'. The next step is to create a folder in your themes directory, called modules. Within it, create another folder with the actual name of the module - in our case, this is blocktopmenu. When loading a module's tpl files, Prestashop first checks to see if there is a file in the activated themes module-override directory with the same name. If so, it will load the themes version instead of the stock one. The menu module's tpl file is named blocktopmenu.tpl, so you have to create a file with the same name in the new folder we just created.

The easiest way to figure out what kind of data a module offers is to either take a look at their tpl file and see what data they use, or load up the {debug} tool. To speed things up, I can tell you that this plugin only offers a single variable, named MENU, which contains a string with all the menu items combined together inside

  • tags. Now, by itself, this doesn't give you a lot of wiggle room, when it comes to customizing the appearance. But, what if you'd like to add something else besides just a li tag for each item? Well, luckily, Smarty to the rescue! This is not an article on Smarty so I'll keep this part short, but, basically, we will use a combination of the string replace function and PHP's explode function to isolate the individual elements. Following that, we can build the HTML code with a foreach loop. Here is my completed template file for this module:

    <div id="menuItems" class="divcollapse">
    	<ul>
    		{assign var=tmpMenu value=$MENU|replace:'<li>':''}
    		{assign var=items value='</li>'|explode:$tmpMenu} 
    		{foreach $items as $item}
    			{if !$item@last}
    		    	<li>{$item}</li>
    		    	{if ($item@index + 2) != $item@total}
    		    		<div class="divcollapse logo"><img src="http://nettuts.s3.amazonaws.com/2169_prestashop/{$img_dir}icon.png" alt="logo"/></div>
    		    	{/if} 
    		    {/if}
    		{/foreach}
    	</ul>
    </div>

    Now this is a lot of new code, so I'll go through it line by line. It begins by opening div and ul tags; these are purely for aesthetic reasons. Next, we use a Smarty command, called assign. This does exactly what it sounds like: it assigns a value to a variable. In the first assign statement, we're removing the opening li tags, and, in the second one, we explode the string by the closing li tag. The result is an array containing a list of menu item links. We then move onto a foreach loop, where we display each item inside

  • tags - except, this time, we've added an icon image after each menu item except for the last menu item. Also, you may have noticed that I'm avoiding the last value in the array all together. This is because the last value is just a newline character.

    If you've executed everything correctly so far, you can now theme it to your liking and add some pages to the menu from the module's "configure" page. Once finished, you should be able to go to your site and see the menu working as expected!


    Conclusion

    This has been a very brief but thorough review of the techniques required to create PrestaShop themes. Over the course of the tutorial, I've gone through the necessary steps to create a full multi-lingual theme, and two different ways to put themed modules into your template.

    Moving forward, I suggest that you dive a bit deeper into Smarty, as it offers a number of hidden features that can really help you out. As for a good place to learn more about Prestashop, well, there's not much; I recommend reading the source. At the time of this writing, Prestashop's documentation is somewhat spotty in its coverage of topics; however, their source code is very well documented. Another excellent option is to examine other modules and themes to gain a deeper understanding of what Prestashop is capable of.

    I hope you've enjoyed reading this article. If you have any questions regarding the article itself, or Prestashop in general, feel free to leave a comment below!

    In need of premium, ready-to-go PrestaShop themes? Check out ThemeForest!

  • Related Posts
    • Code
      Theme Development
      Creating a WordPress Theme from Static HTML: Creating an Archive TemplateCreating wordpress theme from html 400
      If you've been working your way through this series, you now have a functioning theme with two page templates. The steps I've demonstrated to this point are: preparing your markup for WordPress converting your HTML to PHP and splitting your file into template files editing the stylesheet and uploading your theme to WordPress adding a loop to your index file adding meta tags, the wp_head hook and the site title and description to your header file adding a navigation menu adding widget areas to the header and sidebar adding widget areas, a colophon and the wp_footer hook to the footer file creating template files for static pages. Read More…
    • Code
      Theme Development
      Creating a WordPress Theme from Static HTML - Creating a Page TemplateCreating wordpress theme from html 400
      So far in this series, I've shown you how to create a fully functioning WordPress theme from static HTML. We've covered the following steps: preparing your markup for WordPress converting your HTML to PHP and splitting your file into template files editing the stylesheet and uploading your theme to WordPress adding a loop to your index file adding meta tags, the wp_head hook and the site title and description to your header file adding a navigation menu adding widget areas to the header and sidebar adding widget areas, a colophon and the wp_footer hook to the footer file. At the moment, your theme only has one template file for displaying content—the index.php file. A powerful feature of WordPress is the ability to use template files for different kinds of content.Read More…
    • Code
      Theme Development
      Creating a WordPress Theme From Static HTML: The Footer FileCreating wordpress theme from html 400
      In this series, you've been learning how to create a WordPress theme form static HTML. Up to this point, you have: prepared your markup for WordPress converted your HTML to PHP and split your file into template files edited the stylesheet and uploaded your theme to WordPress added a loop to your index file added meta tags, the wp_head hook and the site title and description to your header file added a navigation menu added widget areas to the header and sidebar. Read More…
    • Code
      Theme Development
      Creating a WordPress Theme from Static HTML: Adding NavigationCreating wordpress theme from html 400
      If you've been working through this series, you now have a working theme with template files which you've uploaded to WordPress. In this tutorial, you'll continue to work on the header.php file that you created in Part 2. You'll learn how to add a navigation menu which can be edited via the WordPress Menus admin screen. To do this you'll also need to create a new file for your theme: the functions file.Read More…
    • Code
      Theme Development
      Creating a WordPress Theme From Static HTML: Creating Template FilesCreating wordpress theme from html 400
      In the first part of this series, I showed you how to prepare your HTML and CSS files for WordPress, ensuring the structure would work, the code was valid and that the correct classes were being used. In this tutorial you'll learn how to take your index.html file and split it up into a set of template files for use by WordPress.Read More…
    • Code
      Theme Development
      Creating a WordPress Theme From Static HTML: Preparing the MarkupCreating wordpress theme from html 400
      Last year I did a small (and admittedly very un-scientific) survey among other WordPress developers. What I wanted to know was this: When they built their first WordPress theme, how did they do it? Did they hack an existing theme or did they start with their own static HTML and turn it into a theme? The majority of people I spoke to used the second approach - they were all experienced frontend developers who had built sites using HTML and CSS, and found it easiest to take their existing HTML files and convert them to a theme. Two of the people I spoke to were lecturers or teachers, and told me that this is the approach they use with students. So in this series I'm going to show you how to do just that.Read More…