Кастомизация (переопределение) методов решения

Для того, чтобы переопределить метод в API решения, нужно создать такой же публичный статический метод в пространстве имён Astdesign\Marketpro\Custom.

Это можно сделать и в своих модулях/папках, а можно разместить нужные классы в папке bitrix/modules/astdesign.marketpro/lib/custom (тогда будет работать автозагрузка классов).

Рассмотрим переопределение метода на конкретном примере. Задача - на странице результатов поиска выводить разделы каталога. За страницу поиска в решении отвечает метод \Astdesign\Marketpro\Api\Catalog::searchPage. Кастомизируем его, создав файл bitrix/modules/astdesign.marketpro/lib/custom/api/catalog.php.

Содержимое файла:

<?php

namespace Astdesign\Marketpro\Custom\Api;

use Astdesign\Marketpro\Solution;
use Astdesign\Marketpro\Utils\Options;
use Astdesign\Marketpro\Utils\Search\Correction;

class Catalog
{
    public static function searchPage($data = [])
    {
        Options::set('checkCustomMethodSkip', true);
        $result = \Astdesign\Marketpro\Api\Catalog::searchPage($data);
        if (!empty($result['products']['items'])) {
            $query = trim(htmlspecialcharsbx($data['query']));
            if (!$query || strlen($query) < 3) {
                return $result;
            }
            if (Solution::getOption("useSearchCorrection", "N") === "Y") {
                $query = Correction::getInstance()->correct($query);
            }

            $sectionSearchRes = \Astdesign\Marketpro\Custom\Utils\Search::innerSearchSection($query);
            if (!empty($sectionSearchRes)) {
                $result['sections']['items'] = $sectionSearchRes;
            }
        }
        return $result;
    }
}

В данном примере используется метод Options::set('checkCustomMethodSkip', true); , который позволяет избежать зацикливания при вызове оригинальных методов решения. Его нужно использовать в кастомных методах при каждом вызове оригинальных методов.

В приведённом примере мы для начала вызываем оригинальный метод страницы поиска, который возвращает нам результат, а уже потом мы его модифицируем под свои задачи.

Как это работает внутри

Каждый метод решения, который можно переопределить, начинается с проверки: решение подставляет в имя своего класса Custom — Astdesign\Marketpro\Api\Catalog превращается в Astdesign\Marketpro\Custom\Api\Catalog — и, если такой метод существует и вызываем, отдаёт управление ему. Результат проверки кешируется в пределах запроса, так что накладных расходов почти нет.

Отсюда правила:

  • имя и пространство имён должны совпадать с оригиналом, отличаясь только вставкой Custom;

  • метод должен быть публичным и статическим;

  • переопределить можно только те методы, в которых эта проверка есть — если в начале метода нет checkCustomMethod, перехватить его не получится.

Зачем в примере checkCustomMethodSkip

Строка Options::set('checkCustomMethodSkip', true) перед вызовом оригинала обязательна, если вы хотите дополнить штатный метод, а не заменить его целиком. Без неё оригинальный метод на входе снова увидит ваш переопределённый и вызовет его — получится бесконечная рекурсия.

Флаг одноразовый: решение сбрасывает его при первой же проверке. Поэтому ставьте его непосредственно перед вызовом оригинала, а не в начале своего метода.

Что переживает обновление

Папка lib/custom исключается из пакета обновления, поэтому ваши классы там остаются. Если размещаете переопределения в своём модуле, обновление их тем более не тронет — но тогда позаботьтесь об автозагрузке классов сами.