Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Overrides

Hooks are not always enough: sometimes the behaviour of a core class itself has to change — the price calculation, for example. The legacy core has overrides for that: your class takes the place of a core class and replaces its methods. The mechanism is powerful but fragile, so it matters to know both how it works and why it is avoided.

How it works

Legacy core classes are declared with the Core ending: ProductCore, CartCore. The Product class used by all code is an empty child of ProductCore. That is the class you can replace with your own by putting a file into the override folder:

shop/
├── classes/
│   └── Product.php          class ProductCore
└── override/
    └── classes/
        └── Product.php      class Product extends ProductCore

An override in a module

A module puts the file into its own override folder, repeating the path of the core class:

modules/acmehello/
├── acmehello.php
└── override/
    └── classes/
        └── Product.php
<?php
// modules/acmehello/override/classes/Product.php
class Product extends ProductCore
{
    public function getPrice($tax = true, $id_product_attribute = null, $decimals = 6, ...$rest)
    {
        $price = parent::getPrice($tax, $id_product_attribute, $decimals, ...$rest);
 
        return (int) $this->id_category_default === 12 ? $price * 0.9 : $price;
    }
}

The method calls the parent calculation and lowers the price by ten percent for products of category 12.

Installation

When a module is installed, the engine moves the methods from its override folder into the shop's common override folder; on uninstall it removes them. So after adding the file the module is reset:

php bin/console prestashop:module reset acmehello

Open the file override/classes/Product.php in the shop root: it now has the getPrice() method with a comment saying which module it came from.

What can be overridden

WhatWhere it lives in the module
A core classoverride/classes/Product.php
A front controlleroverride/controllers/front/ProductController.php
A back office controlleroverride/controllers/admin/AdminOrdersController.php

Classes of the new core from the src folder cannot be replaced this way: hooks and Symfony services are used for them.

Why it is a last resort

ProblemWhat it means
ConflictTwo modules cannot override the same method: the second one will not install
UpgradesThe signature of a core method changed — the shop is down
DebuggingBehaviour changes in a non-obvious place
MarketplaceModules with overrides are accepted reluctantly

An override affects the whole shop and all modules at once, so a bug in it breaks pages that have nothing to do with your module.

What to use instead

TaskInstead of an override
Change a priceCatalog price rules or a SpecificPrice object
Add data to a pageA display hook
React to an object being savedThe actionObject...AddAfter, UpdateAfter hooks
Change a back office grid or formThe grid and form hooks from the previous lesson
Change the behaviour of a Symfony serviceService decoration in services.yml

Look for a hook first. An override is for when there really is no hook and the task still has to be solved.

Troubleshooting

In debug mode the "Advanced Parameters → Performance" page has a "Disable all overrides" switch. If the shop behaves strangely, turn it on: when the behaviour is fixed, one of the overrides in the override folder is to blame.

Common mistake

An override file is added or changed, but the behaviour is the same. The engine keeps a class-to-file map in the cache. Delete the file var/cache/prod/class_index.php (in debug mode — var/cache/dev/class_index.php): it is recreated on the next request. The "Clear cache" button in the back office does the same.

Thanks for reading!

Donate to the site — we work hard for you.