Наследование чужого компонента - расширить, не копируя
Меняем поведение штатного компонента, не копируя его целиком: наследуемся от его класса и переопределяем ровно то, что нужно.
Решение
Подключаем класс чужого компонента:
CBitrixComponent::includeComponentClass('bitrix:catalog.section');
class VendorCatalogSection extends CatalogSectionComponent{ // дальше только то, что меняем}Класс чужого компонента подключают отдельной строкой перед объявлением своего. Без неё родительский класс не существует, и страница падает ещё до первого вызова.
Переопределяем один метод:
protected function getResult(){ parent::getResult(); // сначала штатная работа foreach ($this->arResult['ITEMS'] as &$item) { $item['VENDOR_LABEL'] = $this->buildLabel($item); // и наша добавка } unset($item);}Меняют один метод, остальное берут у родителя. Вызов родительской реализации внутри - обязательная часть: без него компонент теряет всё, ради чего его и брали.
Заводим свой компонент рядом:
/local/components/vendor/catalog.section/ class.php - наследник штатного класса .description.php - имя и группа в списке компонентов templates/ - свои шаблоны, если нужны// на странице меняется только имя компонента в вызовеНаследник живёт своим компонентом в своём каталоге. Штатный при этом остаётся нетронутым и продолжает получать исправления вместе с обновлением продукта.
Проверяем после обновления модуля:
// после обновления смотрим, на месте ли переопределённые методы$ref = new ReflectionClass('CatalogSectionComponent');printf("%s: %s\n", 'getResult', $ref->hasMethod('getResult') ? 'есть' : 'ПЕРЕИМЕНОВАН');// такую проверку удобно держать в тестах проекта, а не запускать руками// список переопределённых методов при этом лежит рядом с классом наследникаОбновление продукта меняет чужие методы без предупреждения. Наследование дешевле копии, но не бесплатно: список переопределённых методов проверяют после каждого крупного обновления.
Наследование стоит выбирать тогда, когда меняется поведение, а не разметка. Внешний вид меняют шаблоном, и это не требует ни своего класса, ни своего компонента.
Копию штатного компонента заводят в самую последнюю очередь из всех этих вариантов. Она перестаёт получать исправления в тот же день, а через год отличается от оригинала десятком чужих правок, о которых никто не знает.
Своё поведение полезно держать в отдельных методах, а не вплетать в переопределённые. Тогда при смене родительского метода переносить придётся вызовы, а не саму логику.
Наследование - это осознанная зависимость от чужого кода. Она дешевле копии ровно до того дня, когда автор компонента решит переписать его внутренности; с этой мыслью и стоит выбирать, какой метод трогать, а какой лучше обойти.
Типичные проблемы
Страница падает с ошибкой про неизвестный класс.
Класс родительского компонента не подключён перед объявлением своего. Подключение класса ставят строкой выше объявления своего класса его наследника.
Компонент перестал выводить товары.
Переопределённый метод не вызывает у себя родительскую реализацию этого же метода вовсе. Своя работа идёт до или после неё, а не вместо.
После обновления продукта компонент сломался.
Переопределённый метод в новой версии переименован или изменил сигнатуру. Список таких методов проверяют после каждого крупного обновления самого этого продукта.
Кэш отдаёт результат без ваших изменений.
Свои параметры не попали в ключ кэша компонента. Значения, влияющие на результат работы, обязательно добавляют в этот самый ключ кэша.
Шаблон не видит новых полей.
Поля добавлены после того, как результат ушёл в шаблон. Добавку делают до вывода, а не в самом шаблоне.
Частые вопросы
Когда наследование лучше копии?
Почти всегда: копия перестаёт получать исправления. Копию берут, только когда меняется большая часть кода.
Как узнать имя класса чужого компонента?
Оно объявлено в его файле класса, рядом с логикой. Подключение по имени компонента даёт этот класс.
Можно ли наследовать компонент другого модуля?
Да, механизм не зависит от модуля. Зависимость от чужого кода при этом становится вашей заботой.
Что делать после обновления продукта?
Проверить, на месте ли переопределённые методы, и пройти сценарий. Это дешевле, чем узнать о поломке от покупателя.
Смежное
- Свой компонент - оглавление подтемы
- Свой компонент: структура, параметры, кэш результата - когда пишут с нуля
- Шаблон чужого компонента: копия, доработка результата, эпилог - когда хватает разметки
- Готовое решение в проекте: установка, вмешательство, удаление - та же цена зависимости от чужого кода
- Компоненты 2.0 - устройство компонентов целиком
- Кастомизация изнутри: поиск шаблона, переопределение, кэш - как компонент переопределяется целиком