Creating Modules
Table of contents
/*<![CDATA[*/ div.rbtoc1597330884982 {padding: 0px;} div.rbtoc1597330884982 ul {list-style: disc;margin-left: 0px;} div.rbtoc1597330884982 li {margin-left: 0px;padding-left: 0px;} /*]]>*/
Creating Modules
PrestaShop has a very flexible module system that lets you add functionality to PrestaShop without modifying any of its core files. Much of PrestaShop’s core functionality is also written using modules, which minimises the size of PrestaShop’s core. Unneeded modules can be deleted to save space on the server. The following sections describe how to create various types of PrestaShop modules.
Creating a Basic Module
Creating the Module Files
The first step to creating a module is coming up with a unique directory name for the module. It is convention for a module’s directory name to be all lowercase letters and have one of the following prefixes:
Prefix | Description |
block | Used for modules that appear as a block in the left or right columns. |
graph | Used for graphing modules on the Statistics tab. |
grid | Used for grid modules on the Statistics tab. |
home | Used for modules that appear in the centre column on the homepage. |
product | Used for modules that appear on the product page |
stats | Used for statistics modules on the Statistics tab. |
If the module doesn’t fit any of these categories, then no prefix is used. One way to ensure your module name is unique is to use a vendor suffix. For example, Nethercott Constructions uses the nc suffix on its module names to ensure they are unique.
Once you’ve selected a name, create a directory in the /modules
directory with the name you selected. Next, create a file in the new directory with the same name as the directory followed by .php
. For example, if the name of your module is helloworldnc
, then create a file helloworldnc.php
in the helloworldnc
directory. In that file, copy the required if statement from the top of another module, then add a new class with the same name as the file that extends the Module
class. The case of the class name isn’t important, though it is convention to use an uppercase letter at the start of each word. Here’s an example:
Your module will now appear on the Modules tab in the Other Modules section.
Adding the Constructor
Although your module will now appear in the Other Modules section on the Modules tab, it will not display a name or description. You will need to add a constructor inside the class to add that information. Here’s an example constructor:
The name
variable must be the directory name you chose for the module. The tab
variable is used to select which section the module appears in. It must be one of the following values:
Tab Value | Tab Name |
administration | Administration |
advertising_marketing | Advertising & Marketing |
analytics_stats | Analytics & Stats |
billing_invoicing | Billing & Invoicing |
checkout | Checkout |
content_management | Content Management |
export | Export |
front_office_features | Front Office Features |
i18n_localization | I18n & Localization |
market_place | Market Place |
merchandizing | Merchandizing |
migration_tools | Migration Tools |
others | Other Modules |
payments_gateways | Payments & Gateways |
payment_security | Payment Security |
pricing_promotion | Pricing & Promotion |
quick_bulk_update | Quick / Bulk update |
search_filter | Search & Filter |
seo | SEO |
shipping_logistics | Shipping & Logistics |
slideshows | Slideshows |
smarty_shopping | Smart Shopping |
social_networks | Social Networks |
Any value other than the ones above will place the module in the Other Modules section.
The version
variable can be any number you like. It is used to make it easy to identify which version of the module you are using. It is convention to use numbers below 1.0 before all the planned features have been added to the module, then increment the value as bugs are fixed and more features are added.
The author
variable is the author name displayed after “by” in the module listings. It can also be used to filter modules by author.
Next, the parent constructor is called, which sets the name variable to the module’s ID if no name was provided, then it adds the module to the cache, then creates a _path
variable with the module’s path.
The displayName
variable must be the module name that is displayed in bold on the Modules tab and the description variable must be the description of the module displayed below the module’s name.
The confirmUninstall
variable is an optional variable that lets you specify a confirmation message to display before uninstalling the module. If uninstalling your module will cause important information to be lost, then it is a good idea to add a confirmation message.
The warning variable is another optional variable that lets you specify a warning message to display at the top of the Modules tab. If your module requires information to be entered before it can function correctly, then it is a good idea to check whether it has been set and display a warning if it hasn’t been set.
You must also put a 16 x 16 pixel GIF image called logo.gif
in your module’s directory. Your module should then display on the Modules tab.
Adding the config.xml File
The next thing you should do is add a config.xml
file to your module. Although one isn’t required, it helps to reduce the amount of memory required by the Modules tab by loading only the file instead of the entire module to get the module’s name and description. Here is an example config.xml
file:
The first line is used to define the file as an XML file with UTF-8 encoding. The rest of the file creates a module object with a number of variables. The values of most variables are wrapped in <![CDATA[ ]]>
to prevent the values being parsed as XML. The name
variable is the directory name of the module. It is important for this value to match the module’s directory, otherwise the logo will not display and none of the module links will work.
The displayName
, version
, author
, description
and tab
variables should be the same as the module display name, version, description and tab that you specified in the module’s code. It is best that they match the ones in the module, though no errors will occur if they don’t.
The is_configurable
variable is used to indicate whether the module has a configuration page. If it does, set the variable to 1, otherwise set it to 0. It is important for this value to be correct, otherwise the Configure link may be missing from the module, making it impossible to access the configuration page, or cause an error when it is clicked and no configuration page actually exists.
The need_instance
variable is used to indicate whether an instance of the module needs to be created when the Modules tab is loaded. If the value is 0, then the module will not be loaded, which will save time and memory. If the value is 1, then the module will be loaded. If your module may need to display a warning message on the Modules tab, then you should choose the value 1. Otherwise, choose 0 to save time and memory.
The limited_countries
variable can optionally be used if a module should only be available in a specific country. For example, the following line uses the country ISO code to limit a module to France only:
Adding the Install and Uninstall Functions
Although your module is now displayed on the Modules tab, you won’t be able to install it yet. You will need to add an install()
function inside the class before you can install the module. Here’s an example install()
function:
The install()
function uses an if
statement to call the parent install function, place the module in left column and header hooks, and set variables to their default values. If any of these return false
, then the install()
function will return false
, which causes PrestaShop to display an error message.
If they all return true
, then the install()
function will return true
, which causes PrestaShop to display the "Module installed successfully" message.
It is also a good idea to add an uninstall()
function, so that all the module’s settings are removed from the database when the module is not being used. For example:
The uninstall()
function uses an if statement to call the parent uninstall()
and delete all configuration values related to the module from the database. Like the install function, the uninstall()
function returns false
if any of these return false
or returns true
otherwise, which causes messages similar to the ones above to be displayed.
It is convention for configuration names to be all uppercase and use underscores between words. They must also be no more than 32 characters long, otherwise PrestaShop will display an error message.
You now have a module that can be installed and uninstalled.
Adding the Configuration Page
Although your module can now be installed and uninstalled, you won’t be able to configure the module. If your module has settings that should be easy to change, you should add a configuration page. The getContent() function is called when the Configure link on a module is clicked. It displays the name of the module, then calls the displayForm() function to display the configuration page form. Here’s an example:
This function simply returns a single long text string that contains the HTML of the configuration page. The <form> line is used to post the current configuration settings to the module. If you add a file field as one of the configuration settings, you must change this to the following before the files will be posted:
The <fieldset> line is used to create a box around all related configuration settings and the <legend> line is used to add a label to the top of the box to describe the contents. In the example, the label Settings is used along with the module’s logo. The code $this->l('Settings') is used to make the text translatable via Tools > Translations > Module translations in the Back Office.
The <label> lines are used to display the labels of the configuration setting on the left side of the box and the <div class="margin-form"> lines display the configuration values on the right side of the box.
The first <input> line creates a text field with a unique name name, so it can be identified when it is posted. The value Tools::getValue('name', Configuration::get('HELLO_WORLD_NC_NAME')) makes the text field use the current value of the text field before getting its saved value in the database. This is important, since it allows the text field to retain its value when an error occurs instead of resetting the text field to the saved value. This allows you to see what caused the error instead of wondering why the text field didn’t appear to save.
The <p> lines display descriptions that make it easier to understand what the configuration options do.
The second and third <input> lines are radio buttons that let you turn a configuration option on or off. Both of these inputs have the same name showName, which is used to get the selected radio from the posted data. Each input has a different ID though, which is the name followed by _on for the first input and _off for the second input. The first input has a value of 1 and the second input has a value of 0. After the first input is a green tick image and after the second input is a red cross image. This makes it clear that the first option turns the configuration setting on and the second radio button turns it off. The images are in <label> tags that link the labels to the images, so that clicking on an icon selects the radio button.
Lastly, the <center> line adds a save button at the bottom of the box. It has a unique name submitHelloWorldNC and a value of Save, which is displayed as the label on the button. The class="button" code styles the button using the current Back Office theme.
You should now have a Configure link on your module.
When you click the Configure link, you should see a configuration page.
Saving the Configuration Page Settings
Although you’ve now got a configuration page, you can’t save any of the settings. To do that, you will need to add more code to the getContent() function. Here’s an example:
This function builds upon the previous function by checking whether data was posted, validating the data, and then displaying an error or success message after the module’s name and before the form. The displayErrors()
function groups all the error messages into a single box. The displayConf()
function displays a confirmation message in the new PrestaShop v1.4 style. It is the first if statement in the getContent()
function that checks whether data was posted. The first line in the if statement gets the value of the text field and second line gets the value of the radio buttons. The radio button value is converted to an integer for data validation purposes. If the radio button value isn’t either 0 or 1, then an error message is displayed. This ensures that the setting always has a valid value. If the radio button has a valid value, then the text field and radio button values are written to the database, then a success message is displayed. Your module will now save the configuration settings.
Adding the Hooks
Although your module now has a fully working configuration page, it doesn’t do anything on the website. To make the module do something, you must register hooks the module can be placed in. Here’s an example:
The hookLeftColumn
function defines what code should be added when the module is placed in the left column hook. The first line in the function makes the global $smarty
variable accessible to the function. This variable can be used to pass variables into a template file. The next line gets the text field and radio settings from the database and creates Smarty variables. The last line of the function calls the helloworldnc.tpl
file in the module’s directory, which has access to the Smarty variables that were created. It then returns the HTML generated by the template, which is displayed in place of the {$HOOK_LEFT_COLUMN}
along with the HTML from any other modules that are also in the hook.
The hookRightColumn
function simply calls the hookLeftColumn
function, passing its parameters and returning the result. This is a shortcut that makes it so that the module will display the exact same in either the left or right column. Doing this also makes the code easier to maintain, since you don’t have to worry about changing code in two places.
The hookHeader
function is used to add Javascript and CSS code inside the <head>
tag of the website. Be careful how you use it, since it is easy to confuse it with the hookTop
function, which adds code to the top of the website in the header. The first line in the function adds /modules/helloworldnc/js/examplenc.js
to the list of Javascript files and the second line adds /modules/helloworldnc/css/helloworldnc.css
to the list of CSS files with media type all. This will add the following code in the <head>
tag of the website (if CCC is disabled):
The reason these functions are called instead of adding this code directly is so that the module’s JavaScript and CSS are combined, compressed and cached along with all the other files.
Your module can now be added to the left and right columns.
Adding the Smarty Templates
Although the module can now be added to the left and right columns, it will generate an error, since it references a Smarty template that doesn’t exist. The last step to creating a basic PrestaShop module is to add the Smarty templates.
Smarty templates are files ending in .tpl
that contain HTML code and embedded PHP code using a special Smarty syntax. See the official Smarty documentation for more information. Here’s an example helloworldnc.tpl
:
The first line creates a standard block with a unique ID so that it can be styled independently of other blocks.
The second line adds the label "Message" at the top of the block and makes it translatable in the Back Office. The function name l
stands for language, the parameter s
stands for string and the parameter mod
stands for module. It is important to include the mod
parameter with the name of the module for the translations to appear in the module translations.
The third line creates the content area of the block.
The fourth line adds the message in the content area. When the module has its default configuration, the message will be "Hello, World". If the name is changed on the configuration page, it will also change in the message. If the module has been configured to hide the name, then only "Hello" will be displayed.
You now have a fully functioning module.
Adding CSS and JS
Although you have a fully functioning module, it doesn’t have any CSS or JS, which is usually required to create any module that is useful. In the Adding the Hooks section, you added code to include JavaScript and CSS files in the module, but you didn’t actually put anything inside these files.
It’s a good idea to put the CSS in a separate /css
directory and the JavaScript in a separate /js
directory to keep a clean file structure that matches the structure PrestaShop uses. Here’s an example helloworldnc.css
:
In PrestaShop, it is convention to put CSS blocks containing only one line on a single line, and the last line of a CSS block doesn’t have a semicolon. When there are multiple lines, it is convention to display the lines indented like this:
PrestaShop 1.4.3 uses jQuery v1.4.4, so including it in your module is unnecessary. The only JavaScript you need to include is any third-party libraries you require that build on jQuery. If you need to include inline JavaScript to the module's TPL file, be aware that Smarty will generate an error if there are any curly braces in the code. To prevent the errors, you should add {literal}
before the JavaScript code and {/literal}
after like this:
If you need to combine both JavaScript and Smarty tags, then it's better to replace the JavaScript curly braces with the {ldelim}
and {rdelim}
tags like this:
This code will display the contents of the $message
Smarty variable in a JavaScript alert box when the testFunction()
is called.
Creating a Back Office Tab
The first step to creating a new Back Office tab is coming up with a unique filename ending in .php
. It is convention for a tab’s filename to start with Admin. One way to ensure your tab name is unique is to use a vendor suffix. For example, Nethercott Constructions uses the NC suffix on its tabs to ensure they are unique.
A new tab must be in the following format:
The class name must match the filename of the tab. The name of the class can be anything, though it is convention for the class name to start with Admin
.
The next step is to add the constructor inside the class. Here’s an example constructor:
The first line creates a private variable that contains the Hello World module object. The $this->className
line specifies the class and the $this->table
line specifies which database table is used to store and display data. This can be used to display a table of categories, products or other data from the database. Since this tab is simply a configuration page, the class name is 'Configuration' and the table is 'configuration'.
The $this->_helloWorld
line creates the instance of the Hello World module used later in the tab to display the configuration page. The parent::__construct()
line calls the AdminTab
class constructor, which sets up tab’s ID and default error messages.
Lastly, the display()
and postProcess()
functions need to be added. For example:
To avoid duplicating code, the display()
function calls the displayForm()
function from the Hello World module object to display the same configuration page. The postProcess()
function calls the getContent()
function of the Hello World module object to save the configuration page settings.
Module Hooks
Here's a list of all the module hooks available in PrestaShop. The hooks are listed by title in the Back Office and some have a brief description. The descriptions have been replaced in the table below with more informative explanations of the hooks. By default, only the hooks with a "Position" of 1 are displayed on the Modules > Positions tab. To view all hooks, you must tick the "Display non-positionable hooks" checkbox. Hooks with a "Live Edit" of 1 can have their modules rearranged visually using the "Live Edit" option on the Modules > Positions tab.
To call a hook, use the code Module::hookExec('name')
, where name is from the name column below. In PrestaShop, it is convention to put the code generated by the hook in a variable called HOOK_NAME
. For example, the code to call all the modules in the left column blocks hook and then pass them into a TPL is:
Hook Name | Title | Description | Pos | LE |
payment | Payment | Used in order-payment.tpl to display the payment methods when checking out. | 1 | 1 |
newOrder | New orders | Used to send emails and perform other actions after an order has completed. | 0 | 0 |
paymentConfirm | Payment confirmation | Used by display a confirmation page before payment is completed. | 0 | 0 |
paymentReturn | Payment return | Used in order-confirmation.tpl to display a payment successful message. | 0 | 0 |
updateQuantity | Quantity update | Used for out-of-stock notifications when the quantity of a product changes. | 0 | 0 |
rightColumn | Right column blocks | Used to add blocks in the right column. | 1 | 1 |
leftColumn | Left column blocks | Used to add blocks in the left column. | 1 | 1 |
home | Homepage content | Used to add blocks to centre column on homepage. | 1 | 1 |
header | Header of pages | Used to add JavaScript or CSS inside the | 1 | 0 |
cart | Cart creation and update | Used to run code when a cart is created or updated. | 0 | 0 |
authentication | Successful customer authentication | Used to run code after a customer has successfully logged in. | 0 | 0 |
addproduct | Product creation | Used to run code after a new product is created. | 0 | 0 |
updateproduct | Product Update | Used to run code after a product is modified. | 0 | 0 |
top | Top of pages | Used to add code in header at top of website. | 1 | 0 |
extraRight | Extra actions on the product page (right column). | Used to add blocks below the "Add to cart" block on the product page. | 0 | 0 |
deleteproduct | Product deletion | Used to run code after a product has been deleted. | 0 | 0 |
productfooter | Product footer | Used to add new blocks above the "More info" tab. | 1 | 1 |
invoice | Invoice | Used to add blocks on the right side when viewing order on the Orders tab. | 1 | 0 |
updateOrderStatus | Order’s status update event | Used to run code before the status of an order is changed. | 0 | 0 |
adminOrder | Display in Back-Office, tab AdminOrder | Used to run code before the status of an order is changed. | 0 | 0 |
footer | Footer | Used to add code to footer at bottom of website. | 1 | 0 |
PDFInvoice | PDF Invoice | Used to add extra information to the PDF invoice. | 0 | 0 |
adminCustomer | Display in Back-Office, tab AdminCustomers | Used to add blocks when viewing a customer on the Customers tab. | 0 | 0 |
orderConfirmation | Order confirmation page | Used in order-confirmation.tpl to display an order confirmation message. | 0 | 0 |
createAccount | Successful customer create account | Used to run code after a new customer account has been created. | 0 | 0 |
customerAccount | Customer account page display in front office | Used in my-account.tpl to add more entries on the "My Account" page. | 1 | 0 |
orderSlip | Called when a order slip is created | Used to run code after a credit slip has been created. | 0 | 0 |
productTab | Tabs on product page | Used to adds a new tab to the product page. | 0 | 0 |
productTabContent | Content of tabs on product page | Used to add content to the new tab on the product page. | 0 | 0 |
shoppingCart | Shopping cart footer | Used in shopping-cart.tpl to add a message below the shopping cart. | 0 | 0 |
AdminStatsModules | Stats – Modules | Used to add a statistics module on the Stats tab. | 1 | 0 |
GraphEngine | Graph Engines | Used to add a graph engine used to display statistics on the Stats tab. | 0 | 0 |
orderReturn | Product returned | Used to run code after a merchandise return request has been added. | 0 | 0 |
productActions | Product actions | Used to add buttons below the "Add to cart" button on the product page. | 1 | 0 |
backOfficeHome | Administration panel homepage | Used to add code at the bottom of the Back Office Dashboard. | 1 | 0 |
GridEngine | Grid Engines | Used to add a grid engine to display statistics on the Stats tab. | 0 | 0 |
watermark | Watermark | Used to add a watermark to new images. | 0 | 0 |
cancelProduct | Product cancelled | Used to run code after a product has been removed from an order. | 0 | 0 |
extraLeft | Extra actions on the product page (left column). | Used to add links on the left side of the product page below the image. | 0 | 0 |
productOutOfStock | Product out of stock | Used to run code when a product runs out of stock. | 1 | 0 |
updateProductAttribute | Product attribute update | Used to run code when a product attribute has been updated. | 0 | 0 |
extraCarrier | Extra carrier (module mode) | Used in order-carrier.tpl to add carriers when checking out. | 0 | 0 |
shoppingCartExtra | Shopping cart extra button | Used in shopping-cart.tpl to add code at the bottom of the shopping cart summary. | 1 | 0 |
search | Search | Used to run code after a search has been performed. | 0 | 0 |
backBeforePayment | Redirect in order process | Used to redirect customer to a separate payment page instead payment methods. | 0 | 0 |
updateCarrier | Carrier Update | Used to run code after a carrier has been modified. | 0 | 0 |
postUpdateOrderStatus | Post update of order status | Used to run code after the status of an order has been changed. | 0 | 0 |
createAccountTop | Block above the form for create an account | Used in authentication to add fields to the top of the account registration form. | 1 | 0 |
backOfficeHeader | Administration panel header | Used in header.inc.php to add CSS and JS inside the | 0 | 0 |
backOfficeTop | Administration panel hover the tabs | Used in header.inc.php to add code above the tabs in the Back Office. | 1 | 0 |
backOfficeFooter | Administration panel footer | Used in footer.inc.php to add code above the footer of the Back Office. | 1 | 0 |
deleteProductAttribute | Product Attribute Deletion | Used to run code after a product attribute has been deleted. | 0 | 0 |
processCarrier | Carrier Process | Used to run code after the carrier step has been completed. | 0 | 0 |
orderDetail | Order Detail | Used in order-detail.tpl to add a tracking URL. | 1 | 0 |
beforeCarrier | Before carrier list | Used in order-carrier.tpl to add a message before the carrier list. | 1 | 0 |
orderDetailDisplayed | Order detail displayed | Used in order-detail.tpl to add more information below the addresses. | 1 | 0 |
paymentCCAdded | Payment CC added | Used to run code after credit card details have been added to the database. | 0 | 0 |
extraProductComparison | Extra Product Comparison | Used in product-comparison.tpl to add code to bottom of product comparison table. | 0 | 0 |
categoryAddition | Category creation | Used to run code after a category has been added. | 0 | 0 |
categoryUpdate | Category modification | Used to run code after a category has been modified. | 0 | 0 |
categoryDeletion | Category removal | Used to run code after a category has been deleted. | 0 | 0 |
beforeAuthentication | Before Authentication | Used to run code after login details have been entered, even if they are wrong. | 0 | 0 |
paymentTop | Top of payment page | Used in order-payment.tpl to add a message above all the payment methods. | 0 | 0 |
afterCreateHtaccess | After htaccess creation | Used to run code after the .htaccess file has been generated. | 0 | 0 |
afterSaveAdminMeta | After save configuration in AdminMeta | Used to run code after the Preferences > SEO & URLs tab has been saved. | 0 | 0 |
myAccountBlock | My account block | Used to add more entries to the My Account block. | 0 | 0 |
Last updated