Child pages
  • Creating a first module

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Some PSR fixes in code examples

...

File/folder nameDescriptionDetails
name_of_the_module.phpMain file.

The main PHP file should have the same name as the module's root folder.
For instance, for the BlockCMS module:

  • Folder name: /modules/blockcms
  • Main file name: /modules/blockcms/blockcms.php
config.xmlCache configuration file.If it does not exist yet, this file is automatically generated by PrestaShop when the module is first installed.

logo.gif or logo.jpg (up to v1.4)
logo.png (v1.5+)

Icon files representing this module in the back - office.PrestaShop 1.4: 16*16 pixels Gif or Jpeg file.
PrestaShop 1.5: 32*32 pixels PNG file.
If your module works on both PrestaShop 1.4 and PrestaShop 1.5+, you should have both a logo.gif AND a logo.png file.
/viewsThis folder contains the View files. 
/views/templatesThis folder contains your module's template files (.tpl). If the module needs to work with PrestaShop 1.4, the template files should be placed either directly at at the root of the module's folder, or in a /template folder at the root of the module's folder.
/views/templates/adminSub-folder for template files used by the module's administration controllers. 
/views/templates/frontSub-folder for template files used by the module's front - office controllers. 
/views/templates/hookSub-folder for template files used by the module's hooks. 
/views/templates/cssSub-folder for CSS files used.If the module needs to work with PrestaShop 1.4, the CSS files should be placed in a /css folder at the root of the module's folder.
/views/templates/jsSub-folder for JavaScript files.If the module needs to work with PrestaShop 1.4, the JavaScript files should be placed in a /js folder at the root of the module's folder.
/views/templates/imgSub-folder for image files.If the module needs to work with PrestaShop 1.4, the image files should be placed in a /img folder at the root of the module's folder.
/controllersThis folder contains the Controller files.You can use the same sub-folder paths as for the View files.
For instance, /modules/bankwire/controllers/front/payment.php .
/overrideSub-folder for the class-overriding code.This is very useful when you need to change some of the default PrestaShop code. Since you must not do so, you can override the default code.
For instance, /modules/gsitemap/override/classes/Shop.php extends the default ShopCore class.
/translationsSub-folder for the translation files.fr.php, en.php, es.php, etc.
/themes/[theme_name]/modulesSub-folder for overriding .tpl files and languages files, if necessary.This folder is essential during modifications of an existing module, so that you can adapt it without having to touch its original files. Notably, it enables you to handle the module's template files in various ways, depending on the current theme.
/upgradeSub-folder for upgrade filesWhen releasing a new version of the module, the older might need an upgrade of its data or files. This can be done using this folder.

Only the three first are necessary for a basic module: the main file, the cache configuration file (which is autogenerated by PrestaShop anyway) and the icon file. All the other ones can be used if necessary, but a module can work without them.
The module can also as many other files and folders as necessary: /css, /img, /js, etc.

Info

If wish to use an external library, it should be put in a dedicated folder.

That folder can use one of these names: 'lib', 'libs', 'libraries', 'sdk', 'vendor', 'vendors'.

Choose the most appropriate one for your library (indeed, 'libraries' doesn't not have the same meaning as 'sdk'). You can have more than one such folder, for instance /lib and /sdk.

The PrestaShop coding convention

...

Code Block
<?php	
if (!defined('_PS_VERSION_')) {
  exit;
} 

This checks for the existence of an always-existing PrestaShop constant (its version number), and if it does not exist, it stops the module from loading. The sole purpose of this is to prevent malicious visitors to load this file directly.

...

Code Block
titlemymodule.php
borderStylesolid
<?php
if (!defined('_PS_VERSION_')) {
  exit;
}

class MyModule extends Module
{
}

...

At this stage, if you place the module's folder on the /modules folder, the module can already be seen in the "Modules" page in the back - office, in the "Other modules" section – albeit with no real name nor thumbnail.

...

Code Block
titlemymodule.php
borderStylesolid
<?php
if (!defined('_PS_VERSION_')) {
  exit;
}

class MyModule extends Module
{
  public function __construct()
  {
    $this->name = 'mymodule';
    $this->tab = 'front_office_features';
    $this->version = '1.0.0';
    $this->author = 'Firstname Lastname';
    $this->need_instance = 0;
    $this->ps_versions_compliancy = array('min' => '1.6', 'max' => _PS_VERSION_);	
    $this->bootstrap = true;

    parent::__construct();

    $this->displayName = $this->l('My module');
    $this->description = $this->l('Description of my module.');

    $this->confirmUninstall = $this->l('Are you sure you want to uninstall?');

    if (!Configuration::get('MYMODULE_NAME'))		 {
      $this->warning = $this->l('No name provided');
    }
  }
}

Let's examine each line from this first version of the MyModule class...

...

  • 'name' attribute. This attributes serves as an internal identifier. The value MUST be the name of the module's folder. Do not use special characters or spaces, and keep it lower-case.
  • 'tab' attribute. The title for the section that shall contain this module in PrestaShop's back - office modules list. You may use an existing name, such as seo, front_office_features or analytics_stats, or a custom one. In this last case, a new section will be created with your identifier. We chose "front_office_features" because this first module will mostly have an impact on the front-end.

    Here is the list of available "Tab" attributes, and their corresponding section in the "Modules" page:

    "Tab" attributeModule section
    administrationAdministration
    advertising_marketingAdvertising & Marketing
    analytics_statsAnalytics & Stats
    billing_invoicingBilling & Invoices
    checkoutCheckout
    content_managementContent Management
    dashboardDashboard
    emailingE-mailing
    exportExport
    front_office_featuresFront Office Features
    i18n_localizationI18n & Localization
    market_placeMarket Place
    merchandizingMerchandizing
    migration_toolsMigration Tools
    mobileMobile
    othersOther Modules
    payments_gatewaysPayments & Gateways
    payment_securityPayment Security
    pricing_promotionPricing & Promotion
    quick_bulk_updateQuick / Bulk update
    search_filterSearch & Filter
    seoSEO
    shipping_logisticsShipping & Logistics
    slideshowsSlideshows
    smart_shoppingSmart Shopping
    social_networksSocial Networks
  • 'version' attribute. The version number for the module, displayed in the modules list. It is a string, so that you may use such variation as "1.0b", "3.07 beta 3" or "0.94 (not for production use)".
  • 'author' attribute. This is displayed as-is in the PrestaShop modules list.

...

  • need_instance. Indicates whether to load the module's class when displaying the "Modules" page in the back-officeback office. If set at 0, the module will not be loaded, and therefore will spend less resources to generate the "Modules" page. If your module needs to display a warning message in the "Modules" page, then you must set this attribute to 1.
  • ps_versions_compliancy. Indicates which version of PrestaShop this module is compatible with. In the example above, we explicitly write that this module will only work with PrestaShop 1.5.x, and no other major version.
  • bootstrap. Indicates that the module's template files have been built with PrestaShop 1.6's bootstrap tools in mind – and therefore, that PrestaShop should not try to wrap the template code for the configuration screen (if there is one) with helper tags.

...

Code Block
$this->displayName = $this->l('My module');
$this->description = $this->l('Description of my module.');

$this->confirmUninstall = $this->l('Are you sure you want to uninstall?');

if (!Configuration::get('MYMODULE_NAME'))	 {
    $this->warning = $this->l('No name provided.');  
}

These lines respectively assign:

  • A name for the module, which will be displayed in the back - office's modules list.
  • A description for the module, which will be displayed in the back - office's modules list.
  • A message, asking the administrator if he really does want to uninstall the module. To be used in the installation code.
  • A warning that the module doesn't have its MYMODULE_NAME database value set yet (this last point being specific to our example, as we will see later).

The constructor method is now complete. You are free to add more to it later if necessary, but this the bare minimum for a working module.

Now go to your back - office, in the Modules page: the module is visible in the modules list, with its information displayed – and no icon for now.

...

Code Block
public function install()
{
  if (!parent::install()) {
    return false;
  return}

  return true;
}

In this first and extremely simplistic incarnation, this method does the minimum needed: return true returned by the Module class' install() method, which returns either true if the module is correctly installed, or false otherwise. As it is, if we had not created that method, the superclass' method would have been called instead anyway, making the end result identical.
Nevertheless, we must mention this method, because it will be very useful once we have to perform checks and actions during the module's installation process: creating SQL tables, copying files, creation configuration variables, etc.

...

Code Block
public function install()
{
  if (Shop::isFeatureActive()) {
    Shop::setContext(Shop::CONTEXT_ALL);
  }

  if (!parent::install() ||
    !$this->registerHook('leftColumn') ||
    !$this->registerHook('header') ||
    !Configuration::updateValue('MYMODULE_NAME', 'my friend')
  ) {
    return false;
  }
return
  return true;
}

If any of the lines in the testing block fails, the method returns false and the installation does not happen.

...

Code Block
public function uninstall()
{
  if (!parent::uninstall()) {
    return false;
  }
  
  return true;
}

Building on this foundation, we want an uninstall() method that would delete the data added to the database during the installation ( MYMODULE_NAME configuration setting). This method would look like this:

Code Block
public function uninstall()
{
  if (!parent::uninstall() ||
    !Configuration::deleteByName('MYMODULE_NAME')
  ) {
    return false;
  }

  return true;
}

The Configuration object

...

Code Block
if (Shop::isFeatureActive()) {
  Shop::setContext(Shop::CONTEXT_ALL);
}

As said earlier, here we check that the Multistore feature is enabled, and if so, set the current context to all shops on this installation of PrestaShop.

...

To put the finishing touch to this basic module, you should add an icon, which will be displayed next to the module's name in the back - office modules list.
In case your module is made for a prominent service, having that service's logo visible brings trust.
Make sure you do not use a logo already used by one of the native modules, or without authorization from the owner of the logo/service.

...

Now that all basics are in place, reload the back - office's "Modules" pages, in the "Front - office features" section, you should find your module. Install it (or reset it if it is already installed).

...