Оптовые скидки в списке товаров
Содержание
Описание
Стандартная функциональность
Платформа CS-Cart и Multi-Vendor имеет очень полезный функционал — «Оптовые скидки» (см. Оптовые скидки).
Вы можете задать особые цены на ваши товары при оптовой покупке или для определённых групп покупателей.
Оптовые скидки автоматически применяются при добавлении товара в корзину.
В стандартной функциональности оптовые скидки отображаются в аккуратной таблице на детальной странице товара (карточке товара).
Что будем делать
По умолчанию оптовые скидки не отображаются на странице списка товаров (странице категории). Покупатель узнает о наличии оптовых скидок, только когда зайдёт на карточку товара.
Мы сделаем так, чтобы оптовые скидки отображались и на странице списка товаров.
Было | Стало |
---|---|
Анализ
В CS-Cart обработка и отображении информации разделены. Любая информация которую мы видим в браузере была:
- Обработана, подготовлена и передана на отображение с помощью контроллера — специального PHP скрипта.
- Отображена с помощью шаблона.
Соответственно нам нужно найти:
- PHP функцию которая подготовила информацию об оптовых скидках для товара.
- Шаблон который отобразил информацию.
С чего начать?
Наша задача отобразить оптовые скидки на странице списка товаров. Оптовые скидки отображаются в карточке товара, изучим как это происходит и сделаем тоже самое со списком товаров.
Не интересен процесс? Переходите к финалу: Получим информацию о скидках для страницы списка товаров
Найдём контроллер страницы товара
Всё начинается с контроллера.
Откройте страницу товара на витрине.
Смотрим на URL в адресной строке браузера.
URL:
ваш_домен/index.php?dispatch=products.view&product_id=12
Примечание
Включен модуль SEO? Выключайте! Живой магазин? Делайте копию для экспериментов на поддомене.
Нас интересует параметр
dispatch=products.view
в URL.В данном случае:
products
— это название контроллера который обрабатывает данную страницу.Все контроллеры витрины находятся в папке:
/app/controllers/frontend
Мы определили по URL, что нам нужен контроллер
products
.Открываем файл
/app/controllers/frontend/products.php
Вставляем
fn_print_r('Test');
где нибудь в начале файла контроллера.1 2 3 4 5 6
use Tygh\Registry; use Tygh\BlockManager\ProductTabs; fn_print_r('Test'); if (!defined('BOOTSTRAP')) { die('Access denied'); }
Перезагружаем страницу товара в браузере. Должно отобразится слово
Test
в левом верхнем углу.Отлично, контроллер найден. Однако тут много кода, какой нам нужен?
Снова смотрим на параметр
dispatch=products.view
в URL.Нас интересует часть после точки —
view
.Так обозначается режим (mode) контроллера — секция кода, которая отвечает за данную страницу. (см. О контроллерах)
Значит нам нужно найти блок с условием —
$mode == 'view'
Находим с помощью поиска по файлу блок с нужным условием и вставляем
fn_print_r('Test mode');
в него для проверки.1 2 3 4 5 6 7 8
// // View product details // } elseif ($mode == 'view' || $mode == 'quick_view') { fn_print_r('Test'); $_REQUEST['product_id'] = empty($_REQUEST['product_id']) ? 0 : $_REQUEST['product_id'];
Проверяем в браузере. Должны появится слова
Test mode
Изучаем код. Практически сразу видим предположительное появление информации о товаре.
Добавляем
fn_print_r($product);` чтобы распечатать на экран переменную ``$product
которая появляется в результате работы функцииfn_get_product_data
1 2 3
$product = fn_get_product_data($_REQUEST['product_id'], $auth, CART_LANGUAGE, '', true, true, true, true, fn_is_preview_action($auth, $_REQUEST)); fn_print_r($product);
Смотрим результат в браузере и видим массив с данными о товаре и об оптовых скидках в ячейке
['prices']
:Если мы проследим за дальнейшими действиями над массивом
$product
в контроллере, то увидим:1
Registry::get('view')->assign('product', $product);
Данная строка передаёт массив с данными о товаре
$product
на отображение в шаблоны.
Находим нужную функцию
Мы нашли контроллер и функцию, которая получает данные об оптовых скидках.
Заглянем внутрь функции fn_get_product_data
. Данная функция получает много данные о товаре по product_id
, однако нам нужны только данные об оптовых скидках для страницы категории.
Скорее всего внутри функции fn_get_product_data
есть небольшая функция для получения только оптовых скидок.
1. Все основные функции контроллеров платформы расположены в папке:
/app/functions
Файлы с функциями имеют название соответствующее области работы.
Мы работаем с каталогом, значит нам нужен файл:
fn.catalog.php
.
Открываем
/app/functions/fn.catalog.php
и ищем функциюfn_get_product_data
.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/** * Gets full product data by its id * * @param int $product_id Product ID * @param mixed $auth Array with authorization data * @param string $lang_code 2 letters language code * @param string $field_list List of fields for retrieving * @param boolean $get_add_pairs Get additional images * @param boolean $get_main_pair Get main images * @param boolean $get_taxes Get taxes * @param boolean $get_qty_discounts Get quantity discounts * @param boolean $preview Is product previewed by admin * @param boolean $features Get product features * @param boolean $skip_company_condition Skip company condition and retrieve product data for displayin on other store page. (Works only in ULT) * @return mixed Array with product data */ function fn_get_product_data($product_id, &$auth, $lang_code = CART_LANGUAGE, $field_list = '', $get_add_pairs = true, $get_main_pair = true, $get_taxes = true, $get_qty_discounts = false, $preview = false, $features = true, $skip_company_condition = false, $feature_variants_selected_only = false)
Смотрим параметры передаваемые в функцию.
Очень интересен параметр
$get_qty_discounts
. По смыслу — то что нужно, он должен включать или выключать получение оптовых цен для товара.Находим код, который выполняется для параметра
$get_qty_discounts
.1 2 3 4
// Get qty discounts if ($get_qty_discounts == true) { fn_get_product_prices($product_id, $product_data, $auth); }
Мы нашли конечную функцию
fn_get_product_prices
, которая получает данные об оптовых скидках для товара. Проверим:1 2 3 4 5 6
// Get qty discounts if ($get_qty_discounts == true) { fn_print_r($product_data['prices']); fn_get_product_prices($product_id, $product_data, $auth); fn_print_r($product_data['prices']); }
Первый
fn_print_r
пустой, а второй уже содержит информацию о скидках.Результат:
Переходим к странице списка товаров
Мы нашли функцию которая нам нужна. Наша цель отобразить оптовые скидки на странице списка товаров. Найдём и изучим контроллер целевой страницы:
Открываем страницу списка товаров (страницу категории).
Смотрим URL в браузере, чтобы определить контроллер.
Нам по прежнему важен параметр
dispatch=categories.view
, где:- Контроллер —
categories
- Режим (mode) —
view
- Контроллер —
Открываем файл:
app/controllers/frontend/categories.php
Находим раздел с
$mode == 'view'
и вставим функциюfn_print_r('Test Cat');
для проверки.1 2 3
} elseif ($mode == 'view') { fn_print_r('Test Cat');
Перезагрузим страницу в браузере, чтобы проверить. Если увидите
Test Cat
, то вы там где нужно.Ищем по смыслу функцию, которая получает информацию о товарах. Можно просто перебирать переменные с помощью
fn_print_r()
.После недолгого поиска, находится
fn_get_products
, которая создаёт массив с товарами$products
:1 2 3
list($products, $search) = fn_get_products($params, Registry::get('settings.Appearance.products_per_page'), CART_LANGUAGE); fn_print_r($products);
Распечатаем
$products
.Изучаем массив данных и не находим информации об оптовых скидках. Идём дальше по коду контроллера categories.php.
Находим функцию
fn_gather_additional_products_data
, данная функция получает дополнительную информацию о товарах. Судя по параметрам, есть подозрение, что она может получать оптовые скидки.1 2 3
list($products, $search) = fn_get_products($params, Registry::get('settings.Appearance.products_per_page'), CART_LANGUAGE); fn_print_r($products);
Распечатываем
$products
после функции и изучаем массив с данными.К сожалению, информации о оптовых скидках не появилось. У функции есть параметр
'get_discounts' => true,
, судя по названию, он связан со скидками. Зайдём и посмотрим.Зайдём и изучим функцию
fn_gather_additional_products_data
.Функция находится в файле
/app/functions/fn.catalog.php
.Находим код отрабатывающий по параметру:
'get_discounts' => true,
1 2
// Get product discounts if ($params['get_discounts'] && !isset($product['exclude_from_calculate'])) {
К сожалению, функции в данном условии отвечают за получение скидок по «Промо-акциям» для каталога.
Данная функция не получает информацию об оптовых скидках.
Однако в данной функции есть много хуков и возможно нам они понадобятся.
Хуки в php выглядят так.
1
fn_set_hook('gather_additional_product_data_before_discounts', $product, $auth, $params);
Хуки позволяют подключить и выполнить свой php код, используя данные переданные в хук.
Возвращаемся в контроллер categories.php и идём дальше по коду.
Доходим до строки, которая передаёт данные о товарах в Smarty шаблон на отображение. Дальше информация о товаре не будет расширятся.
Распечатаем переменную
$products
перед передачей её на отображение1 2
fn_print_r($products); Registry::get('view')->assign('products', $products);
Просмотрим результат в браузере и в очередной раз убедимся, что нет информации об оптовых скидках.
Будем добавлять.
Получим информацию о скидках для страницы списка товаров
Мы изучили контроллер categories.php, отвечающий за информацию для страницы списка товаров, и не нашли информации о скидках.
Значит нам нужно её добавить.
Мы нашли функцию fn_get_product_prices
которая по id товара сможет получить информацию о скидках.
Мы нашли хуки в одной из функций которые выполняет контроллер categories.php.
Подключимся к хуку и расширим данные товаров информацией о скидках.
Расширять будем с помощью модуля «Мои изменения».
Рассмотрим хук из функции
fn_gather_additional_products_data
.1
fn_set_hook('gather_additional_product_data_before_discounts', $product, $auth, $params);
Первый аргумент функции
fn_set_hook
соответствует названию хука.Последующие аргументы
$product
,$auth
,$params
соответствуют данным которые будут доступны для модификации в хуке.Для подключения к хуку, хук необходимо инициализировать.
Создайте новый файл:
/app/addons/my_changes/init.php
Вставьте код для инициализации хука:
1 2 3 4 5
<?php fn_register_hooks( 'gather_additional_product_data_before_discounts' );
Мы передали названия хука в функцию
fn_register_hooks
, можно инициализировать сколько угодно хуков, передавая через запятую. Посмотрети в других модулях.Чтобы выполнить свой php код в хуке, создайте файл:
/app/addons/my_changes/func.php
Создайте в данном файле новую функцию с названием вида:
fn_[идентификатор_модуля]_[название_хука]
В качестве аргументов функции используйте переменные передаваемые в хук.
1 2 3 4 5 6 7 8 9 10 11
<?php if (!defined('BOOTSTRAP')) { die('Access denied'); } function fn_my_changes_gather_additional_product_data_before_discounts(&$product, &$auth, &$params) { fn_print_r('ID товара: ' . $product['product_id']); return true; }
Включите модуль «Мои изменения» и проверьте подключение к хуку.
Вы должны увидеть распечатанные идентификаторы товаров, потому что хук к которому мы подключаемся выполняется в цикле по всем товарам. В данной ситуации нам подходит именно этот хук, в ином случае мы бы стали искать другой.
У нас есть всё что бы получить нужные данные.
Выполним функцию
fn_get_product_prices
и получим данные о скидках.1 2 3 4 5 6 7 8 9 10 11 12 13
<?php if (!defined('BOOTSTRAP')) { die('Access denied'); } function fn_my_changes_gather_additional_product_data_before_discounts(&$product, &$auth, &$params) { fn_get_product_prices($product['product_id'], $product, $auth); fn_print_r($product['prices']); return true; }
Результат:
Мы используем стандартную функцию из детальной страницы товара. Как видите функция расширила данные о товаре информацией о скидками. Информация о скидках записалась в ячейку
['prices']
так же как и в контроллере детальной страницы товара. Товары у которых нет оптовых цен не имеют ячейки['prices']
.Обратите внимание, что аргументы
(&$product, &$auth, &$params)
переданы в хук ссылками, поэтому изменения в хуке выходят наружу и влияют на работу всего скрипта.Убираем
fn_print_r
из хука и переносим его в контроллер categories.php, в то место где переменная$products
передаётся на отображение. Делаем это, чтобы проверить появились ли данные о скидках вне модуля.1 2
fn_print_r('Проверяем работу хука',$products[0]['product'],$products[0]['prices']); Registry::get('view')->assign('products', $products);
Я передал на распечатку название и оптовые скидки первого по порядку товара в массиве
$products
, потому что оптовые скидки в примере настроенны именно для этого товара.
Отлично, данные о скидках получены.
Убираем все fn_print_r
в функциях и контроллерах и переходим к шаблонам.
Оптовые скидки уже появились на странице списка товаров
Было | Стало |
---|---|
Почему скидки появились сразу?
Всё дело в шаблонах, в шаблоне отвечающего за выбор количеств товара было условие: «Если есть информация об оптовых скидках, то отображаем».
Откроем детальную страницу товара и посмотрим код блока оптовых скидок в браузере:
Все шаблоны находятся в папке:
/design/themes/[название_темы]/templates/
Сделаем поиск по файлам в папке c шаблонами, будем искать файл в котором встречается класс
ty-qty-discount__table
, который использует таблица скидок.Поиск нашёл всего один такой файл:
/design/themes/[название_темы]/templates/views/products/components/products_qty_discounts.tpl
Откроем файл и добавим
<p>Test</p>
в любое место.Контрольная фраза появилась. Отлично.
Найдём где подключается данный шаблон уровнем выше.
Делаем поиск по файлам, ищем
products/components/products_qty_discounts.tpl
в папке с шаблонами.Поиск находит всего один файл:
/design/themes/[название_темы]/templates/common/product_data.tpl
Открываем данный файл и находим подключение нужного нам шаблона и условие:
1 2 3
{if $product.prices} {include file="views/products/components/products_qty_discounts.tpl"} {/if}
Добавим
<p>Test 1</p>
.Шаблоны найдены, убираем все тесты.
Когда мы с помощью хука расширили информацию о товарах, добавив оптовые скидки, они сразу же появились, под блоком выбора товаров.
Cкидки не появились сразу?
Попробуйте выключить параметры тестового товара.
Возможно ваш тестовый товар имеет параметры и комбинации параметров. В этом случае не отображается выбора количества товара, а именно в этом шаблоне срабатывает вывод оптовых скидок. Кроме того кнопка «Купить» заменяется на «Выберите параметры».
Вы можете воспользоваться уроком Отображение опций в списке.
Спасибо! Если возникнут вопросы, пишите в комментариях.