Категории форума

Полное руководство по функции cot_market_enum()

функция cot_market_enum() — это мощный генератор списков товаров для модуля Market в Cotonti. Она позволяет вывести товары в любом месте сайта: на главной странице, в сайдбаре, в профиле пользователя, в произвольном плагине и т.д.

webitproff
webitproff • 10.09.2026 02:56 #593

Полное руководство по функции cot_market_enum()

Функция cot_market_enum() — это мощный генератор списков товаров для модуля Market в Cotonti. Она позволяет вывести товары в любом месте сайта: на главной странице, в сайдбаре, в профиле пользователя, в произвольном плагине и т.д. Возвращает готовую HTML-строку, которую можно вывести напрямую или передать в шаблон.

1. Что делает функция?

cot_market_enum() формирует SQL-запрос к таблице товаров cot_market, применяет заданные фильтры (категории, условия, статус, даты), сортировку, при необходимости ограничивает количество и пагинацию, затем рендерит результаты через шаблон market.enum.tpl (или пользовательский) и возвращает итоговый HTML.

Она объединяет в себе:

  • выборку из базы данных;
  • обработку категорий (включая подкатегории и чёрный список);
  • фильтрацию по активности (опубликованные, дата начала/окончания);
  • поддержку дополнительных условий;
  • постраничную навигацию;
  • кэширование;
  • интеграцию с комментариями (если плагин активен);
  • вызов хуков для расширения.

2. Сигнатура и параметры

function cot_market_enum(
    $categories = '',
    $count = 0,
    $template = '',
    $order = '',
    $condition = '',
    $active_only = true,
    $use_subcat = true,
    $exclude_current = false,
    $blacklist = '',
    $pagination = '',
    $cache_ttl = null
)

2.1. $categories (string|array)

Категории, товары которых нужно показать.

  • Если '' — будут выбраны товары из всех категорий.
  • Можно указать строку с кодами категорий через запятую: 'electronics,books'.
  • Можно передать массив: ['electronics', 'books'].
  • Внутри функция преобразует строку в массив, убирает дубликаты.
  • Если $use_subcat = true (по умолчанию), то к каждой указанной категории будут добавлены все её подкатегории (рекурсивно). Для этого используется cot_structure_children().
  • Если $blacklist не пуст, то категории из чёрного списка будут исключены из итогового списка.
// Только категория 'electronics' и её подкатегории
cot_market_enum('electronics', 10);

// Категории 'electronics' и 'books' без подкатегорий
cot_market_enum(['electronics', 'books'], 10, '', '', '', true, false);

2.2. $count (int)

Количество товаров для вывода.

  • 0 — вывести все товары, удовлетворяющие условиям (если пагинация выключена).
  • Если $pagination задан (не пустая строка), то $count интерпретируется как количество товаров на одну страницу.
  • Если $count > 0 и пагинация выключена, будет выведено только указанное количество (обычно последние/первые в зависимости от сортировки).
// Показать 5 последних товаров
cot_market_enum('', 5);

// Показать все товары (осторожно, может быть много)
cot_market_enum('', 0);

2.3. $template (string)

Имя части шаблона или путь к файлу шаблона для рендеринга виджета.

  • Если '' или не указан, используется стандартный шаблон модуля: market.enum.tpl.
  • Рекомендуемый способ: передайте имя части шаблона, например 'sidebar'. Функция вызовет cot_tplfile(['market', 'enum', 'sidebar'], 'module'), который сначала ищет файл в теме (themes/ваша_тема/modules/market/enum.sidebar.tpl), а затем в модуле (modules/market/tpl/market.enum.sidebar.tpl). Такой подход позволяет легко переопределять шаблоны в теме.
  • Можно указать и полный путь к файлу (например, 'modules/market/tpl/market.enum.custom.tpl'), если файл существует. Однако этот метод менее гибкий и привязывает к конкретному расположению.
// Рекомендуется: указать имя части шаблона
cot_market_enum('', 5, 'sidebar'); // будет искать market.enum.sidebar.tpl

// Альтернатива: полный путь (работает, но менее предпочтительно)
cot_market_enum('', 5, 'modules/market/tpl/market.enum.sidebar.tpl');

2.4. $order (string)

SQL-выражение для сортировки.

  • Если не задано (''), используется 'ORDER BY fieldmrkt_date DESC' — сначала новые.
  • Вы можете указать любое валидное SQL-выражение после ORDER BY. Например:
    • 'fieldmrkt_costdflt ASC' — по возрастанию цены;
    • 'fieldmrkt_title ASC' — по алфавиту;
    • 'fieldmrkt_updated DESC' — по дате обновления.

Важно: поле должно существовать в таблице cot_market. Стандартные поля: fieldmrkt_id, fieldmrkt_title, fieldmrkt_desc, fieldmrkt_text, fieldmrkt_costdflt, fieldmrkt_date, fieldmrkt_updated, fieldmrkt_count и другие.

cot_market_enum('', 10, '', 'fieldmrkt_costdflt DESC'); // дорогие сверху

2.5. $condition (string)

Дополнительное SQL-условие (без слова WHERE).

  • Позволяет фильтровать товары по любым полям.
  • Строка будет вставлена в секцию WHERE в дополнение к остальным условиям.
  • Нужно следить за экранированием и корректностью SQL.
// Только товары дороже 100
cot_market_enum('', 0, '', '', 'fieldmrkt_costdflt > 100');

// Товары с определённым артикулом
cot_market_enum('', 5, '', '', "fieldmrkt_pcod = 'ABC123'");

2.6. $active_only (bool)

Показывать только опубликованные и активные товары.

  • Если true (по умолчанию), добавляются условия:
    • fieldmrkt_state = 0 — опубликован;
    • fieldmrkt_begin <= {текущее время} — дата начала публикации уже наступила;
    • fieldmrkt_expire = 0 OR fieldmrkt_expire > {текущее время} — срок окончания не истёк.
  • Если false, будут показаны все товары, включая черновики, на модерации и просроченные (будьте осторожны с правами доступа).
// Показать все товары без ограничений (например, для админки)
cot_market_enum('', 10, '', '', '', false);

2.7. $use_subcat (bool)

Включать подкатегории при выборке по категориям.

  • Если true (по умолчанию), для каждой указанной категории будут добавлены все её потомки (на любую глубину).
  • Если false, будут выбраны товары только из точно указанных категорий.
// Только родительская категория, без подкатегорий
cot_market_enum('electronics', 10, '', '', '', true, false);

2.8. $exclude_current (bool)

Исключить текущий просматриваемый товар.

  • Работает только если константа COT_MARKET определена и мы не на странице списка (COT_LIST не определена).
  • Использует глобальную переменную $id (ID текущего товара).
  • Полезно на странице товара, чтобы показывать "похожие товары" без самого товара.
// На странице товара: показать 5 товаров из той же категории, кроме текущего
cot_market_enum($item_data['fieldmrkt_cat'], 5, '', 'fieldmrkt_date DESC', '', true, true, true);

2.9. $blacklist (string|array)

Чёрный список категорий.

  • Категории, которые нужно исключить из выборки.
  • Можно передать строку с кодами через запятую: 'system,drafts' или массив: ['system', 'drafts'].
  • Если категории не заданы (первый параметр пуст), то товары из этих категорий будут исключены из общего списка.
  • Если категории заданы, то чёрный список применяется к ним (удаляет указанные коды).
// Показать все товары, кроме служебных категорий
cot_market_enum('', 10, '', '', '', true, true, false, 'system,drafts');

2.10. $pagination (string)

Имя GET-параметра для постраничной навигации.

  • Если пустая строка '' — пагинация отключена.
  • Если задано, например 'p', функция будет:
    • обрабатывать параметр p из URL для определения текущей страницы;
    • выводить только $count товаров на текущей странице;
    • генерировать HTML пагинации (ссылки на другие страницы).
  • Параметр передаётся в cot_pagenav(), поэтому в URL появятся ссылки вида ?p=2.
// Пагинация по 5 товаров, параметр 'p'
cot_market_enum('', 5, '', 'fieldmrkt_date DESC', '', true, true, false, '', 'p');

2.11. $cache_ttl (int|null)

Время жизни кэша в секундах.

  • Если null или 0 — кэширование отключено.
  • Если > 0, то сгенерированный HTML сохраняется в дисковый кэш Cotonti (если он включён) с указанным TTL.
  • Ключ кэша зависит от шаблона, языка и SQL-запроса (с заменой текущего времени на _time_), поэтому при изменении данных товаров кэш может устареть. Рекомендуется использовать умеренные значения (например, 300–3600 секунд).
// Кэшировать на 10 минут
cot_market_enum('', 5, '', 'fieldmrkt_date DESC', '', true, true, false, '', '', 600);

3. Как функция работает внутри (краткий обзор)

  1. Обработка чёрного списка: строка преобразуется в массив.
  2. Обработка категорий:
    • Если $categories не пуст, преобразуется в массив.
    • Если $use_subcat включён, для каждой категории вызывается cot_structure_children() для получения всех потомков.
    • Применяется чёрный список.
    • Формируется условие fieldmrkt_cat IN (...).
    • Если категории не указаны, но есть чёрный список, формируется условие fieldmrkt_cat NOT IN (...).
  3. Дополнительное условие $condition добавляется в WHERE.
  4. Исключение текущего товара (если включено).
  5. Фильтр активности (если $active_only): добавляются условия по статусу и датам.
  6. Пагинация: если $pagination задан, вычисляется смещение $d через cot_import_pagenav().
  7. Выбор шаблона: если $template не пуст и файл существует (или имя части шаблона), используется он; иначе стандартный market.enum.tpl.
  8. Хук market.enum.query: позволяет модифицировать запрос (таблицы, колонки).
  9. Подключение комментариев (если активен плагин): добавляется подзапрос для подсчёта количества комментариев.
  10. Формируются SQL-запросы:
    • $sql_total — для подсчёта общего количества (для пагинации);
    • $sql_query — для выборки данных (с JOIN пользователей).
  11. Кэширование: проверяется наличие кэша; если найден — возвращается готовый HTML.
  12. Выполнение запроса выборки и цикл по результатам:
    • для каждого товара генерируются теги через cot_generate_markettags() (префикс MARKET_ROW_);
    • добавляются дополнительные теги: MARKET_ROW_NUM, MARKET_ROW_ODDEVEN, MARKET_ROW_RAW;
    • генерируются теги владельца (MARKET_ROW_OWNER_...);
    • хук market.enum.loop;
    • если комментарии активны, добавляются теги MARKET_ROW_COMMENTS_LINK и MARKET_ROW_COMMENTS_COUNT;
    • блок MAIN.MARKET_ROW парсится.
  13. Пагинация: если включена, строится cot_pagenav() и присваиваются теги пагинации.
  14. Хук market.enum.tags.
  15. Финальный парсинг блока MAIN, сохранение в кэш (если нужно) и возврат HTML.

4. Примеры использования

4.1. В PHP-коде (контроллер, плагин)

Простой вывод последних 5 товаров

$html = cot_market_enum('', 5);
echo $html;

Вывод товаров из категории "electronics" с подкатегориями

$html = cot_market_enum('electronics', 10);
echo $html;

Передача в шаблон

$t->assign('MARKET_LATEST', cot_market_enum('', 5, '', 'fieldmrkt_date DESC'));

Виджет для сайдбара: популярные товары (по просмотрам)

$sidebar_market = cot_market_enum('', 5, '', 'fieldmrkt_count DESC');
$t->assign('SIDEBAR_MARKET', $sidebar_market);

Товары со скидкой (цена < 50), отсортированные по цене

$html = cot_market_enum('', 10, '', 'fieldmrkt_costdflt ASC', 'fieldmrkt_costdflt < 50');
echo $html;

Исключить текущий товар на странице товара

if (defined('COT_MARKET') && !defined('COT_LIST')) {
    $html = cot_market_enum($item_data['fieldmrkt_cat'], 5, '', 'fieldmrkt_date DESC', '', true, true, true);
    echo $html;
}

Использование в плагине

// Внутри вашего плагина
function myplugin_show_market_widget() {
    if (cot_module_active('market')) {
        require_once cot_incfile('market', 'module');
        return cot_market_enum('', 5, '', 'fieldmrkt_date DESC');
    }
    return '';
}

4.2. В шаблонах Cotonti (через тег {PHP|...})

Внимание: в шаблонах можно вызывать функцию напрямую, но лучше это делать в PHP и передавать переменную, чтобы не смешивать логику и представление. Однако для простых случаев возможно.

<!-- 5 последних товаров -->
<div>{PHP|cot_market_enum('', 5, '', 'fieldmrkt_date DESC')}</div>

<!-- 6 товаров из категории 'books' с пагинацией по 3 (параметр p) -->
<div>{PHP|cot_market_enum('books', 3, '', 'fieldmrkt_date DESC', '', true, true, false, '', 'p')}</div>

Примечание: в теге {PHP|...} нельзя использовать echo. Функция должна возвращать строку, которая будет выведена автоматически.

5. Настройка шаблонов виджета

Стандартный шаблон находится в modules/market/tpl/market.enum.tpl. Вы можете:

  1. Переопределить в теме: создайте файл themes/yourtheme/modules/market/enum.tpl — он будет использован автоматически.
  2. Указать другой файл через параметр $template (имя части шаблона или полный путь).

Внутри шаблона доступны блоки:

  • <!-- BEGIN: MAIN --> ... <!-- END: MAIN --> — основной контейнер.
  • <!-- BEGIN: MARKET_ROW --> ... <!-- END: MARKET_ROW --> — повторяется для каждого товара.

Внутри MARKET_ROW можно использовать теги, сгенерированные cot_generate_markettags() с префиксом MARKET_ROW_. Например:

  • {MARKET_ROW_TITLE} — заголовок товара (экранирован)
  • {MARKET_ROW_URL} — ссылка на товар
  • {MARKET_ROW_TEXT_SHORT} — краткое описание
  • {MARKET_ROW_COSTDFLT} — цена
  • {MARKET_ROW_CAT_TITLE} — название категории
  • и другие (полный список в функции cot_generate_markettags)

Дополнительные теги, добавляемые функцией cot_market_enum:

  • {MARKET_ROW_NUM} — порядковый номер
  • {MARKET_ROW_ODDEVEN}odd или even
  • {MARKET_ROW_RAW} — массив данных товара (для отладки)
  • {MARKET_ROW_OWNER_NAME} и другие теги владельца, если используется cot_generate_usertags()
  • {MARKET_ROW_COMMENTS_COUNT}, {MARKET_ROW_COMMENTS_LINK} — если активен плагин comments

Пример минимального шаблона:

<!-- BEGIN: MAIN -->
<div class="market-widget">
    <!-- BEGIN: MARKET_ROW -->
    <div class="item {MARKET_ROW_ODDEVEN}">
        <a href="{MARKET_ROW_URL}">{MARKET_ROW_TITLE}</a>
        <div class="price">{MARKET_ROW_COSTDFLT}</div>
    </div>
    <!-- END: MARKET_ROW -->
</div>
<!-- END: MAIN -->

6. Важные замечания и возможные ошибки

  • Безопасность: параметр $condition вставляется в SQL-запрос как есть. Не передавайте в него неэкранированные пользовательские данные. Используйте подготовленные выражения, если нужно.
  • Права доступа: функция не проверяет права пользователя на чтение категорий. Если вы используете её на публичной странице, убедитесь, что $active_only = true, чтобы не показывать скрытые товары. Для админки можно ставить false.
  • Производительность: при большом количестве товаров и выключенном кэше функция может создавать нагрузку. Используйте кэш ($cache_ttl) для статичных виджетов.
  • Пагинация: если включена, обязательно укажите $count > 0. В противном случае cot_pagenav() может работать некорректно.
  • Совместимость: функция использует глобальные переменные $db, $db_market и др. Убедитесь, что модуль Market подключён (require_once cot_incfile('market', 'module');).
  • Хуки: если вы пишете плагин, вы можете влиять на выборку через хуки market.enum.query, market.enum.loop, market.enum.tags.

7. Как вывод

cot_market_enum() — гибкий инструмент для отображения списков товаров. Освоив её параметры и принципы работы, вы сможете легко встраивать товарные виджеты в любые части сайта, не написав ни строчки SQL. Для сложных сценариев используйте комбинацию параметров, хуков и собственных шаблонов.

8. Вызов функции cot_market_enum() прямо в шаблонах Cotonti

Cotonti использует шаблонизатор CoTemplate (класс XTemplate), который поддерживает вставку PHP-функций через тег {PHP|...}. Внутри таких тегов можно вызывать любые глобальные функции, в том числе cot_market_enum(). Функция должна возвращать строку, которая будет автоматически выведена в месте вызова. Использование echo внутри тега не требуется и приведёт к ошибке.

Общая форма вызова в шаблоне:

{PHP|cot_market_enum(аргументы)}

Все параметры функции передаются так же, как в PHP-коде, но в одной строке. Для удобства чтения можно переносить аргументы? В шаблонах переносы внутри тега возможны, но лучше держать всё в одной строке.

8.1. Простые примеры

<!-- Показать 5 последних товаров из всех категорий -->
<div class="latest-products">
    {PHP|cot_market_enum('', 5, '', 'fieldmrkt_date DESC')}
</div>

<!-- Показать 6 товаров из категории 'electronics' и её подкатегорий -->
<div class="electronics-products">
    {PHP|cot_market_enum('electronics', 6, '', 'fieldmrkt_date DESC')}
</div>

<!-- Показать товары с пагинацией по 4 на страницу (параметр p) -->
<div class="paged-products">
    {PHP|cot_market_enum('', 4, '', 'fieldmrkt_date DESC', '', true, true, false, '', 'p')}
</div>

8.2. Примеры с дополнительными условиями

<!-- Товары дороже 100, сортировка по цене -->
<div class="expensive-products">
    {PHP|cot_market_enum('', 8, '', 'fieldmrkt_costdflt ASC', 'fieldmrkt_costdflt > 100')}
</div>

<!-- Товары из категории 'books' без подкатегорий, только опубликованные -->
<div class="books-no-subcat">
    {PHP|cot_market_enum('books', 5, '', 'fieldmrkt_date DESC', '', true, false)}
</div>

8.3. Исключение текущего товара

Если шаблон используется на странице товара (когда определена константа COT_MARKET и не определена COT_LIST), можно вывести похожие товары, исключив текущий:

<div class="related-products">
    {PHP|cot_market_enum(PHP.cat, 5, '', 'fieldmrkt_date DESC', '', true, true, true)}
</div>

Внимание: здесь предполагается, что в шаблоне доступна переменная {PHP.cat} с кодом текущей категории. Если это не так, лучше подготовить значение в PHP-коде и передать в шаблон, а затем вызвать функцию с этим значением.

8.4. Использование кэширования

<div class="cached-widget">
    {PHP|cot_market_enum('', 5, '', 'fieldmrkt_date DESC', '', true, true, false, '', '', 600)}
</div>

8.5. Важные замечания при вызове в шаблоне

  • Функция cot_market_enum() должна быть доступна в области видимости шаблона. Она определена в файле modules/market/inc/market.functions.php, который подключается при загрузке модуля Market. Убедитесь, что модуль активен и файл функций загружен.
  • Все строки с кавычками внутри аргументов должны быть корректно экранированы для HTML. Используйте одинарные кавычки для строк в PHP-вызове, чтобы не конфликтовать с двойными кавычками атрибутов HTML.
  • Не используйте echo внутри {PHP|...}. Результат функции выводится автоматически.
  • Для сложных условий и передачи массивов лучше предварительно вычислить результат в PHP-коде и передать его в шаблон через assign(). Прямой вызов в шаблоне подходит для простых случаев, когда параметры статичны.
  • Если вы используете пагинацию, убедитесь, что в URL передаются все необходимые параметры. Функция сама построит ссылки на основе текущего URL, но лучше тестировать.
  • Производительность: каждый вызов в шаблоне порождает отдельный SQL-запрос. Для часто используемых виджетов рекомендуется кэширование ($cache_ttl).

Таким образом, вы можете быстро добавить списки товаров в любые части шаблонов вашей темы без изменения PHP-кода, если модуль Market уже загружен.

🗿

🧙‍♂️ Радуйся, странниче добрый и честный! Не понапрасну привела тя стезя в земли сии. Зде бо мужи мудры и искусники дела писменнаго и численнаго, что куют словеса и плетут узоры кода, тайны разгадывают и знанием делятся, летописи множа и ремесло цифровое творя.
⬅️ Аще налево пойдеши — обрящеши грамоты древния, писания старинныя и свитки учения. ⬆️ Аще прямо — слово мудрое и совет от мужей разумеющих, что в деле кодописном искусны, получиши. ➡️ Аще направо — сам в писцы и летописцы внидеши, и в ремесло цифровое, где строки и знаки в дело живое обращаются, слово свое в память веков вложиши.
📝 Не медли же — нареки имя свое, и вниди в чин наш, и стань с нами в братстве, где код есть магия, а строки — заклятия живыя, числом и буквою слово едины суть.
🏰 Не тайно есть собрание сие, и не инициации в нем, но многое сокрыто от пришлых и ступалого, понеже не всякому открывается знание, но токмо ищущим и пребывающим в деле сем.