SuperAPI AI Directory

prestashop

Coding & development

View repository

Updated 10-15 20:06

About this skill

PrestaShop Module Development

Overview

PrestaShop is an open-source PHP e-commerce platform that has undergone significant architectural evolution. PrestaShop 1.7+ introduced Symfony components for the back office, and PrestaShop 8.x completed the transition to a Symfony-first architecture for all admin pages. Modules remain the primary extension mechanism, built as self-contained PHP packages that integrate through a powerful hook system, ObjectModel ORM (legacy), Doctrine ORM (modern), and Symfony service containers.

A PrestaShop module is a directory inside /modules/ containing at minimum a main PHP class file and a config.xml descriptor. The main class extends Module and implements install(), uninstall(), and hook callback methods. Modules can add admin pages, modify the storefront, extend the checkout, integrate payment gateways, add shipping carriers, and interact with the PrestaShop webservices API.

PrestaShop 8.x runs on PHP 7.2.5+ (PHP 8.1 recommended), Symfony 4.4, and supports MySQL 5.6+ or MariaDB 10.x. The template engine is Smarty for the front office and Twig for the back office (Symfony controllers). Understanding both rendering engines is essential for full-stack module development.

For detailed directory structure, module lifecycle, ObjectModel, and Doctrine entity patterns, see references/module-architecture.md.

Module Structure

Every module follows a predictable directory layout. The module name must match the directory name and the main class name, using lowercase alphanumeric characters and underscores only.

Main Module File

The main file (mymodule.php) defines a class extending Module. The constructor sets metadata:

class MyModule extends Module
{
    public function __construct()
    {
        $this->name = 'mymodule';
        $this->tab = 'front_office_features';
        $this->version = '1.0.0';
        $this->author = 'Author Name';
        $this->need_instance = 0;
        $this->ps_versions_compliancy = ['min' => '1.7.0.0', 'max' => '8.99.99'];
        $this->bootstrap = true;

        parent::__construct();

        $this->displayName = $this->l('My Module');
        $this->description = $this->l('Module description.');
    }
}

config.xml

PrestaShop reads config.xml to display module information in the back office before loading PHP. This file mirrors the constructor metadata and is auto-generated on first install but should be maintained manually for marketplace submissions.

composer.json

Modern modules include composer.json for autoloading and dependency management. Use PSR-4 autoloading to organize classes into namespaces. Register the autoloader in the main module file or rely on PrestaShop's module autoloader for simple structures.

Controllers

Modules can register front controllers (customer-facing pages) and admin controllers (back office pages). Front controllers extend ModuleFrontController and live in controllers/front/. Admin controllers extend ModuleAdminController (legacy) or use Symfony controllers with routes defined in config/routes.yml.

Views

Template files for the front office use Smarty (.tpl extension) stored in views/templates/front/. Admin templates for Symfony controllers use Twig (.html.twig) stored in views/templates/admin/. CSS and JavaScript assets go in views/css/ and views/js/.

For the complete directory tree and file conventions, see references/module-architecture.md.

Hook System

Hooks are the primary integration mechanism in PrestaShop. They allow modules to inject content into specific locations (display hooks) or react to system events (action hooks). PrestaShop defines hundreds of hooks across the front office, back office, and core business logic.

Display Hooks

Display hooks inject HTML at specific template positions:

  • displayHeader -- Add CSS/JS to the page <head>.
  • displayHome -- Render content on the homepage.
  • displayProductExtraContent -- Add tabs or sections to the product page.
  • displayShoppingCartFooter -- Add content below the cart summary.
  • displayPaymentReturn -- Show confirmation content after payment.
  • displayBackOfficeHeader -- Add assets to the admin header.

Action Hooks

Action hooks fire when business events occur:

  • actionProductSave -- Triggered after a product is saved in the back office.
  • actionOrderStatusUpdate -- Triggered when an order status changes.
  • actionCartSave -- Triggered when the cart is modified.
  • actionCustomerAccountAdd -- Triggered when a new customer registers.
  • actionValidateOrder -- Triggered during order validation (before finalization).

Hook Registration

Register hooks in the install() method. Every hook the module uses must be explicitly registered:

public function install()
{
    return parent::install()
        && $this->registerHook('displayHome')
        && $this->registerHook('actionOrderStatusUpdate');
}

Implement the hook callback as a method named hook + hook name (camelCase):

public function hookDisplayHome($params)
{
    $this->context->smarty->assign(['variable' => 'value']);
    return $this->display(__FILE__, 'views/templates/front/home.tpl');
}

For the complete hook catalog, custom hook creation, and advanced registration patterns, see references/hooks-reference.md.

Development Setup

Docker Environment

Use the official PrestaShop Docker image for local development:

services:
  prestashop:
    image: prestashop/prestashop:8-apache
    ports:
      - "8080:80"
    environment:
      DB_SERVER: db
      DB_NAME: prestashop
      DB_USER: root
      DB_PASSWD: admin
      PS_INSTALL_AUTO: 1
      PS_DOMAIN: localhost:8080
      PS_FOLDER_ADMIN: admin-dev
    volumes:
      - ./modules/mymodule:/var/www/html/modules/mymodule
    depends_on:
      - db
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: admin
      MYSQL_DATABASE: prestashop

Mount the module directory as a volume to enable live code reloading. Access the admin panel at http://localhost:8080/admin-dev.

Module Generator

Use the PrestaShop module generator to scaffold a new module:

# Install the generator globally
composer global require prestashop/module-generator

# Generate a module skeleton
prestashop:module:generate mymodule

Alternatively, copy a minimal module template and customize. Enable debug mode in config/defines.inc.php by setting _PS_MODE_DEV_ to true for detailed error reporting during development.

Development Tools

  • PrestaShop Console -- CLI tool for cache clearing, module installation, and database migrations.
  • Symfony Debug Toolbar -- Available in the back office when debug mode is enabled. Shows queries, hooks, and service container.
  • PHP CS Fixer -- Use the PrestaShop coding standards configuration for consistent formatting.

Key Integration Patterns

Payment Modules

Payment modules extend PaymentModule and implement specific hooks and interfaces. The payment flow in PrestaShop 1.7+/8.x uses the paymentOptions hook:

public function hookPaymentOptions($params)
{
    $option = new PrestaShop\PrestaShop\Core\Payment\PaymentOption();
    $option->setModuleName($this->name)
           ->setCallToActionText($this->l('Pay by Card'))
           ->setAction($this->context->link->getModuleLink($this->name, 'validation', [], true));

    return [$option];
}

Implement a validation front controller that processes the payment, calls the gateway API, and uses $this->module->validateOrder() to create the order. Handle success, failure, and pending states. Store the transaction ID on the order for reference.

Carrier Modules

Carrier modules extend CarrierModule and implement getOrderShippingCost() and getOrderShippingCostExternal(). Register the carrier in install() using the Carrier ObjectModel. Return shipping rates based on cart weight, dimensions, and destination.

Admin Controllers

Legacy admin controllers extend ModuleAdminController and use HelperForm and HelperList for rendering. Modern modules should use Symfony controllers with Twig templates and register routes in config/routes.yml. Both approaches are covered in detail in references/admin-and-backoffice.md.

Symfony Integration (PrestaShop 8.x)

PrestaShop 8.x embraces Symfony conventions for back office development. Modules can define services, use dependency injection, register Symfony routes, and render Twig templates.

Service Definition

Define services in config/services.yml:

services:
  mymodule.product_service:
    class: MyModule\Service\ProductService
    arguments:
      - '@doctrine.orm.entity_manager'
      - '@prestashop.adapter.legacy.context'

Routing

Register routes in config/routes.yml:

mymodule_admin_settings:
  path: /mymodule/settings
  methods: [GET, POST]
  defaults:
    _controller: 'MyModule\Controller\Admin\SettingsController::indexAction'
    _legacy_controller: AdminMyModuleSettings
    _legacy_link: AdminMyModuleSettings

Modern Controllers

Symfony controllers extend FrameworkBundleAdminController and use Twig for rendering:

use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;

class SettingsController extends FrameworkBundleAdminController
{
    public function indexAction(Request $request)
    {
        return $this->render('@Modules/mymodule/views/templates/admin/settings.html.twig', [
            'layoutTitle' => 'My Module Settings',
        ]);
    }
}

For complete Symfony integration patterns including form handling, CQRS commands, and Grid components, see references/admin-and-backoffice.md.

Webservices API

PrestaShop includes a built-in REST-like webservices API for external integrations. The API exposes resources (products, orders, customers, categories) as XML or JSON endpoints with API key authentication.

Modules can extend the webservices by registering custom resources through the addWebserviceResources hook. This allows external systems to interact with module-specific data through the standard PrestaShop API.

For complete webservices documentation including CRUD operations, filtering, and custom resource creation, see references/webservices-api.md.

Anti-Patterns

Avoid these common mistakes in PrestaShop module development:

  • Direct database queries bypassing ObjectModel -- Use ObjectModel subclasses or Doctrine entities for data access. Raw SQL creates upgrade fragility and skips validation hooks.
  • Overriding core classes -- PrestaShop supports class overrides in /override/, but overrides conflict between modules and break on core updates. Use hooks instead.
  • Hardcoded SQL table prefixes -- Always use _DB_PREFIX_ constant. PrestaShop installations may use custom table prefixes.
  • Ignoring multishop context -- PrestaShop supports multiple shops from a single installation. Always check Shop::getContext() and scope queries to the active shop.
  • Storing configuration in files -- Use Configuration::updateValue() and Configuration::get() for module settings. File-based config breaks in multi-server and multishop environments.
  • Skipping uninstall cleanup -- Remove database tables, configuration values, hooks, and tabs in uninstall(). Leftover data causes errors on reinstall.
  • Using deprecated payment hooks -- PrestaShop 1.7+ replaced displayPayment and displayPaymentEU with paymentOptions. Use the modern approach for compatibility.

For deeper guidance on each anti-pattern and recommended alternatives, consult the relevant reference files linked throughout this document.

Reference Files

  • Module Architecture -- Directory structure, module lifecycle, ObjectModel, Doctrine entities, configuration management, auto-upgrade
  • Hooks Reference -- Display hooks, action hooks, custom hooks, hook registration, widget hooks, dynamic hooks
  • Webservices API -- REST API, XML/JSON output, API key auth, resource endpoints, CRUD operations, filtering, custom resources
  • Admin and Back Office -- Legacy vs Symfony controllers, HelperForm, HelperList, Twig templates, Grid components, module configuration pages
  • Marketplace Publishing -- PrestaShop Addons submission, technical validation, module checker, documentation requirements, pricing, version compatibility