Development of Product Review System in 1C-Bitrix
1C-Bitrix has a built-in forum mechanism (forum) and component bitrix:forum.reviews that can technically serve as a review system. However, most projects abandon it: excessive forum structure for simple reviews, complex moderation setup, poor integration with product cards. In practice, reviews are built either on infoblocks or ORM models from scratch.
Two Approaches to Review Storage
Approach 1: Review Infoblock. Quick, no development, but limited. Create "Reviews" infoblock with properties: PRODUCT_ID (product binding), RATING (number), ADVANTAGES, DISADVANTAGES, COMMENT. Infoblock element = one review. For product binding use "Infoblock Element" property or simple numeric field with product ID.
Output — component bitrix:catalog.reviews (if available in template) or custom component based on CIBlockElement::GetList() with filter PROPERTY_PRODUCT_ID = $productId.
Approach 2: Custom ORM Model. More flexible: transactions, complex queries, extensibility. Table b_product_review:
| Field | Type | Purpose |
|---|---|---|
| ID | int auto_increment | Primary key |
| PRODUCT_ID | int | Product ID in infoblock |
| USER_ID | int | User ID (NULL for guests) |
| AUTHOR_NAME | varchar(255) | Author name |
| AUTHOR_EMAIL | varchar(255) | Email for notifications |
| RATING | tinyint | Rating 1–5 |
| ADVANTAGES | text | Advantages |
| DISADVANTAGES | text | Disadvantages |
| COMMENT | text | Main text |
| STATUS | enum | PENDING, APPROVED, REJECTED |
| CREATED_AT | datetime | Creation date |
| IS_VERIFIED_PURCHASE | tinyint(1) | Did user purchase this product |
ORM class inherits from \Bitrix\Main\ORM\Data\DataManager — get standard D7 API for queries, add, update.
Purchase Verification
One of key trust indicators for a review is "Verified Purchase". To set IS_VERIFIED_PURCHASE flag when submitting review, check order history:
function isVerifiedPurchase(int $userId, int $productId): bool
{
$orders = \Bitrix\Sale\OrderTable::getList([
'filter' => ['=USER_ID' => $userId, '=STATUS_ID' => 'F'],
'select' => ['ID'],
]);
$orderIds = array_column(iterator_to_array($orders), 'ID');
if (empty($orderIds)) {
return false;
}
$basket = \Bitrix\Sale\BasketTable::getList([
'filter' => [
'=ORDER_ID' => $orderIds,
'=PRODUCT_ID' => $productId,
],
'select' => ['ID'],
'limit' => 1,
])->fetch();
return (bool)$basket;
}
Status 'F' is completed order. Check only completed to filter out cancelled and unpaid.
Review Moderation
New reviews get PENDING status. In admin area create custom page (or section in local/admin/) with review table and "Approve" / "Reject" buttons. On status change:
-
APPROVED→ review becomes visible on site, product average rating is recalculated. -
REJECTED→ review hidden, optionally send email to author.
Notification about new review for moderator — email event REVIEW_NEW_PENDING, template in Settings → Email Events.
Product Rating Recalculation
After approving or deleting review, recalculate average rating and save to product property (e.g., AVERAGE_RATING numeric type). Speeds up rating display on catalog pages — no JOIN with reviews table on each query.
function recalculateProductRating(int $productId): void
{
$result = \Bitrix\Main\Application::getConnection()->query(
"SELECT AVG(RATING) as AVG_RATING, COUNT(*) as CNT
FROM b_product_review
WHERE PRODUCT_ID = {$productId} AND STATUS = 'APPROVED'"
)->fetch();
\CIBlockElement::SetPropertyValuesEx($productId, false, [
'AVERAGE_RATING' => round((float)$result['AVG_RATING'], 1),
'REVIEW_COUNT' => (int)$result['CNT'],
]);
}
Called from event handler on review status change.
Anti-spam and Limits
- Check for duplicate reviews: one user — one review per product (check by
USER_ID + PRODUCT_IDor byAUTHOR_EMAIL + PRODUCT_IDfor guests). - CAPTCHA for guests (component
bitrix:main.captcha). - Rate limiting: one IP cannot submit more than 3 reviews per hour (via
\Bitrix\Main\Data\Cacheor table with timestamps).
Development Timeframe
| Scope | Components | Duration |
|---|---|---|
| Basic | ORM model, form, output, moderation in personal account | 4–6 days |
| Full | Purchase verification, rating recalculation, notifications, anti-spam, admin section | 8–12 days |







