Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Переопределения

Хуков хватает не всегда: иногда нужно изменить само поведение класса ядра — например, расчёт цены. Для этого в старом ядре есть переопределение (override): свой класс встаёт на место класса ядра и подменяет его методы. Механизм мощный, но хрупкий, поэтому важно знать и как он работает, и почему его избегают.

Как это устроено

Классы старого ядра объявлены с окончанием Core: ProductCore, CartCore. Сам класс Product, которым пользуется весь код, — пустой наследник ProductCore. Именно его и можно заменить своим, положив файл в папку override:

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

Переопределение в модуле

Модуль кладёт файл в свою папку override, повторяя путь к классу ядра:

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;
    }
}

Метод вызывает родительский расчёт и снижает цену на десять процентов для товаров категории 12.

Установка

При установке модуля движок переносит методы из его папки override в общую папку override магазина, при удалении — убирает их. Поэтому после добавления файла модуль сбрасывают:

php bin/console prestashop:module reset acmehello

Откройте файл override/classes/Product.php в корне магазина: в нём появился метод getPrice() с комментарием, из какого модуля он пришёл.

Что можно переопределить

ЧтоГде лежит в модуле
Класс ядраoverride/classes/Product.php
Контроллер витриныoverride/controllers/front/ProductController.php
Контроллер панелиoverride/controllers/admin/AdminOrdersController.php

Классы нового ядра из папки src так заменить нельзя: для них служат хуки и службы Symfony.

Почему это крайняя мера

ПроблемаВ чём она
КонфликтДва модуля не могут переопределить один метод: второй не установится
ОбновленияСигнатура метода ядра изменилась — магазин упал
ОтладкаПоведение меняется в неочевидном месте
МаркетплейсМодули с переопределениями принимают неохотно

Переопределение действует на весь магазин и на все модули сразу, поэтому ошибка в нём ломает страницы, никак не связанные с вашим модулем.

Чем заменить

ЗадачаВместо переопределения
Изменить ценуПравила цен каталога или объект SpecificPrice
Добавить данные на страницуХук вывода
Реагировать на сохранение объектаХуки actionObject...AddAfter, UpdateAfter
Изменить таблицу или форму панелиХуки таблиц и форм из прошлого урока
Изменить поведение службы SymfonyДекорирование службы в services.yml

Сначала ищите хук. Переопределение — когда хука действительно нет, а задачу решить нужно.

Поиск неисправности

На странице «Расширенные параметры → Производительность» в режиме отладки есть переключатель «Отключить все переопределения». Если магазин ведёт себя странно, включите его: когда поведение исправилось, виновато одно из переопределений в папке override.

Частая ошибка

Файл переопределения добавили или изменили, а поведение прежнее. Движок хранит карту «класс — файл» в кеше. Удалите файл var/cache/prod/class_index.php (в режиме отладки — var/cache/dev/class_index.php): он создастся заново при следующем запросе. Кнопка «Очистить кеш» в панели делает то же.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.