Development of Product Comparison Module for 1C-Bitrix
The standard Bitrix distribution includes the bitrix:catalog.compare component and built-in session-based comparison cart. On simple projects this suffices. But as soon as requirements appear — store list between sessions, compare products from different categories, highlight differing characteristics, export table — the standard component hits its ceiling. A custom module solves these tasks without workarounds.
How Built-in Comparison Works and Where It Breaks
The built-in mechanism stores the list in $_SESSION['CATALOG_COMPARE'] and in the catalog_compare_items cookie. When adding a product, the component's AJAX method writes to the session. Problems:
- Session lives until browser closes or timeout — user returns the next day and the list is empty.
- No category separation — you can add a TV and boots to comparison, and the component tries to compare them.
- Characteristics are displayed without highlighting differences.
- No support for authenticated users: one person on two devices — two different lists.
Module Architecture
The module registers in the system via local/modules/vendor.compare/ with standard include.php and install/index.php. List storage:
Table b_compare_list:
| Field | Type | Purpose |
|---|---|---|
| ID | int auto_increment | Primary key |
| USER_ID | int | Authenticated user ID, NULL for guests |
| SESSION_ID | varchar(64) | Session hash for guests |
| CREATED_AT | datetime | Creation date |
| UPDATED_AT | datetime | Last modification date |
Table b_compare_item:
| Field | Type | Purpose |
|---|---|---|
| ID | int auto_increment | — |
| LIST_ID | int | FK to b_compare_list |
| PRODUCT_ID | int | Product offer ID |
| SECTION_ID | int | Catalog section ID |
| ADDED_AT | datetime | When added |
ORM classes inherit from \Bitrix\Main\ORM\Data\DataManager. Limit on number of products in one list is set via module settings (table b_option, module namespace).
Merge Logic on Login
When a guest logs in, their anonymous list needs to be merged with permanent:
public static function mergeOnLogin(int $userId, string $sessionId): void
{
$guestList = CompareListTable::getRow([
'filter' => ['=SESSION_ID' => $sessionId, '=USER_ID' => false],
]);
if (!$guestList) {
return;
}
$userList = CompareListTable::getOrCreate($userId);
$guestItems = CompareItemTable::getList([
'filter' => ['=LIST_ID' => $guestList['ID']],
]);
foreach ($guestItems as $item) {
CompareItemTable::addIfNotExists($userList['ID'], $item['PRODUCT_ID']);
}
CompareListTable::delete($guestList['ID']);
}
The OnAfterUserLogin event from the main module is the place to call this method.
Highlighting Differing Characteristics
This is what the customer expects from comparison: rows where products differ should be visually highlighted. Algorithm:
- Get properties of all products in comparison via
CIBlockElement::GetList()withSELECT = ['PROPERTY_*']. - Build a matrix: key — property code, value — array of values for each product.
- For each matrix row check
count(array_unique($values)) > 1— if more than one unique value, mark as "different". - On frontend, add CSS class
compare-row--diffto rows with differences.
Additionally filter rows where all values are empty — they don't need to be shown.
Frontend: AJAX and State
The "Add to Comparison" button on the product card sends POST to the component via bitrix:main.ajax. Icon state (added / not added) is synchronized via localStorage on page load and updated after each AJAX response.
Product count in comparison is displayed in header via separate component, which reads count from session or module API without loading full data.
Exporting Comparison Table
Large projects request export to PDF or Excel. For PDF use mPDF or TCPDF (connected as dependency via composer in local/). For Excel — PhpSpreadsheet. The comparison table is formed from the same property matrix and rendered to file on user request.
Development Timeline
| Scale | Content | Duration |
|---|---|---|
| Basic | DB storage, AJAX add/remove, comparison table | 4–6 days |
| Standard | + Merge on login, highlight differences, header counter | 8–10 days |
| Extended | + PDF/Excel export, cross-category comparison, module settings in admin | 12–16 days |







