Разработка подбора размера по параметрам на 1С-Битрикс
Конвертер размеров помогает тем, кто уже знает свой размер в одной системе. Подбор по параметрам решает другую задачу: покупатель знает свои мерки — рост, вес, обхват груди, длину стопы, — но не знает, какой размер ему подойдёт в конкретном бренде. Или знает, что у разных производителей он носит разные размеры, и хочет получить рекомендацию именно для данного товара.
Это самый «умный» из инструментов размерной навигации — и самый сложный в реализации.
В чём сложность
Подбор по параметрам требует связи между тремя наборами данных:
- Мерки покупателя — рост, вес, обхват груди/талии/бёдер, длина стопы
- Размерная сетка товара — соответствие размерных обозначений физическим меркам (с учётом допусков на посадку: облегающий или свободный крой)
- Остатки — рекомендованный размер может отсутствовать на складе, нужно предлагать альтернативу
И если для одежды подбор относительно прямолинеен (грудь → размер), то для обуви включается вопрос полноты (широкая стопа требует другой колодки), а для спортивного инвентаря — технические характеристики (длина клюшки по росту и стилю игры).
Архитектура данных
Расширяем структуру из таблицы размеров дополнительными параметрами допусков:
CREATE TABLE b_size_fit_rules (
ID SERIAL PRIMARY KEY,
CHART_ID INT NOT NULL REFERENCES b_size_charts(ID),
SIZE_RU VARCHAR(10),
-- Диапазоны мерок для этого размера
CHEST_MIN NUMERIC(5,1), CHEST_MAX NUMERIC(5,1),
WAIST_MIN NUMERIC(5,1), WAIST_MAX NUMERIC(5,1),
HIPS_MIN NUMERIC(5,1), HIPS_MAX NUMERIC(5,1),
HEIGHT_MIN SMALLINT, HEIGHT_MAX SMALLINT,
WEIGHT_MIN SMALLINT, WEIGHT_MAX SMALLINT,
-- Тип посадки (влияет на допуск)
FIT_TYPE VARCHAR(20) -- 'slim', 'regular', 'oversized'
);
Ключевой момент — диапазоны мерок, а не точные значения. Размер 46 подходит для груди 88–92 см, а не строго для 90 см. Ширина диапазона зависит от типа посадки: slim fit — узкий диапазон, oversized — широкий.
Алгоритм подбора
// SizeFitAdvisor.php
class SizeFitAdvisor {
public function recommend(array $measurements, int $chartId, string $fitType = 'regular'): array {
$rules = SizeFitRulesTable::getList([
'filter' => ['=CHART_ID' => $chartId, '=FIT_TYPE' => $fitType],
'order' => ['SIZE_RU' => 'ASC'],
])->fetchAll();
$scores = [];
foreach ($rules as $rule) {
$score = 0;
$matched = 0;
// Для каждой переданной мерки проверяем попадание в диапазон
foreach (['CHEST', 'WAIST', 'HIPS'] as $param) {
if (!isset($measurements[$param])) continue;
$val = (float) $measurements[$param];
$min = (float) $rule[$param . '_MIN'];
$max = (float) $rule[$param . '_MAX'];
if ($val >= $min && $val <= $max) {
$score++;
} elseif ($val < $min) {
$score -= ($min - $val) / 10; // штраф за отклонение
} else {
$score -= ($val - $max) / 10;
}
$matched++;
}
if ($matched > 0) {
$scores[$rule['SIZE_RU']] = $score / $matched;
}
}
arsort($scores); // сортируем по убыванию очков
$best = array_key_first($scores);
$next = array_keys($scores)[1] ?? null; // второй вариант на случай отсутствия
return ['primary' => $best, 'alternative' => $next, 'scores' => $scores];
}
}
Алгоритм возвращает не один размер, а основную рекомендацию и альтернативу. Это важно: если основной размер недоступен, показываем альтернативу с пометкой «если 46 нет, возьмите 48 — подойдёт при вашем телосложении».
Проверка доступности рекомендованного размера
После получения рекомендации — немедленная проверка остатков:
public function checkAvailability(string $sizeRu, int $productId): array {
// Ищем торговые предложения с данным размером
$offers = \Bitrix\Iblock\ElementTable::getList([
'filter' => [
'=IBLOCK_ID' => OFFERS_IBLOCK_ID,
'=PROPERTY_CML2_LINK' => $productId,
'=PROPERTY_SIZE_VALUE' => $sizeRu,
'=ACTIVE' => 'Y',
],
'select' => ['ID', 'PROPERTY_QUANTITY'],
])->fetchAll();
$available = array_filter($offers, fn($o) => (int)$o['PROPERTY_QUANTITY_VALUE'] > 0);
return [
'available' => count($available) > 0,
'offers' => $available,
];
}
Форма подбора на карточке товара
UX-паттерн: ссылка «Подобрать размер» под выбором размеров открывает модальное окно или разворачивает форму.
Одношаговая форма (все мерки сразу) — для опытных покупателей:
<form class="size-advisor-form">
<div class="form-row">
<label>Рост (см): <input type="number" name="height" min="140" max="220"></label>
<label>Вес (кг): <input type="number" name="weight" min="40" max="200"></label>
</div>
<div class="form-row">
<label>Обхват груди (см): <input type="number" name="chest" min="60" max="160"></label>
<label>Обхват талии (см): <input type="number" name="waist" min="50" max="150"></label>
<label>Обхват бёдер (см): <input type="number" name="hips" min="70" max="170"></label>
</div>
<label>Посадка:
<select name="fit_type">
<option value="slim">Облегающая</option>
<option value="regular" selected>Стандартная</option>
<option value="oversized">Свободная</option>
</select>
</label>
<button type="submit">Подобрать размер</button>
</form>
Пошаговый опрос — для тех, кто не привык к таким формам. Одно поле на экране, с прогресс-баром. Меньше когнитивной нагрузки, но длиннее процесс.
AJAX-запрос к PHP-контроллеру
Форма отправляет данные на сервер, а не обрабатывается на JS, потому что:
- Алгоритм подбора на сервере — данные не доступны конкурентам
- Сервер сразу проверяет остатки и возвращает финальный ответ
- Результат можно персонализировать (сохранить мерки для авторизованного пользователя)
// SizeAdvisorController.php — действие AJAX
public function recommendAction(): array {
$measurements = [
'CHEST' => (float) $this->request->getPost('chest'),
'WAIST' => (float) $this->request->getPost('waist'),
'HIPS' => (float) $this->request->getPost('hips'),
];
$fitType = $this->request->getPost('fit_type', 'regular');
$productId = (int) $this->request->getPost('product_id');
$chartId = $this->getChartForProduct($productId);
$advisor = new SizeFitAdvisor();
$result = $advisor->recommend($measurements, $chartId, $fitType);
$availability = $advisor->checkAvailability($result['primary'], $productId);
// Сохраняем мерки авторизованного пользователя
if (is_object(global_user()) && !global_user()->IsGuest()) {
UserMeasurementsTable::saveForUser(global_user()->GetID(), $measurements);
}
return [
'recommended_size' => $result['primary'],
'alternative_size' => $result['alternative'],
'available' => $availability['available'],
'offers' => $availability['offers'],
];
}
Сохранение мерок в личном кабинете
Если пользователь авторизован, мерки сохраняются и подставляются при следующем обращении к советнику — даже на другом товаре:
CREATE TABLE b_user_measurements (
USER_ID INT PRIMARY KEY REFERENCES b_user(ID),
HEIGHT_CM SMALLINT,
WEIGHT_KG SMALLINT,
CHEST_CM NUMERIC(5,1),
WAIST_CM NUMERIC(5,1),
HIPS_CM NUMERIC(5,1),
FOOT_MM INT,
DATE_UPDATE TIMESTAMP DEFAULT NOW()
);
В личном кабинете — раздел «Мои мерки» для ручного редактирования.
Сроки
| Вариант | Что входит | Срок |
|---|---|---|
| Базовый советник (JS + таблица данных) | Форма, алгоритм, результат | 1–2 недели |
| С проверкой остатков и альтернативами | + интеграция с ТП, остатки | 2–3 недели |
| + ЛК с мерками, история рекомендаций | + сохранение профиля | +1 неделя |
Советник по размеру на основе мерок даёт наиболее точную рекомендацию и максимально снижает вероятность возврата. Из всех размерных инструментов — самый трудоёмкий, но и самый эффективный.







