PHPackages                             beeralex/beeralex.reviews - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. beeralex/beeralex.reviews

ActiveBitrix-module

beeralex/beeralex.reviews
=========================

My reviews module

v1.2.0(3mo ago)04MITPHP

Since Oct 6Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/BkycHblu-6oPwuK/beeralex.reviews)[ Packagist](https://packagist.org/packages/beeralex/beeralex.reviews)[ RSS](/packages/beeralex-beeralexreviews/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (1)Versions (10)Used By (0)

Модуль beeralex.reviews
=======================

[](#модуль-beeralexreviews)

Система управления отзывами для Bitrix с поддержкой модерации, загрузки файлов и REST API.

Основные возможности
--------------------

[](#основные-возможности)

- ✅ **Создание отзывов** с автоматической валидацией (PHP 8.2+ атрибуты)
- 📁 **Загрузка файлов** (фото к отзывам)
- 🔐 **Модерация** — новые отзывы требуют одобрения
- 👤 **Авторизованные и гостевые** пользователи
- ⭐ **Рейтинг 1-5** звезд
- 📥 **Импорт отзывов** из 2GIS (deprecated)
- 🔄 **Сортировка** (новые/старые)
- 🌐 **REST API** интеграция

Требования
----------

[](#требования)

- PHP 8.2+
- Bitrix Framework 25.0+ (рекомендуемая для php 8.2)
- Модуль `beeralex.core` (базовые абстракции)
- Инфоблок с кодом `product_reviews`

Установка
---------

[](#установка)

### Через Composer

[](#через-composer)

Добавьте в `composer.json`:

```
"extra": {
  "installer-paths": {
    "local/modules/{$name}/": ["type:bitrix-module"]
  }
}
```

Установите пакет:

```
composer require beeralex/beeralex.reviews
```

### Ручная установка

[](#ручная-установка)

1. Разместите модуль в `/local/modules/beeralex.reviews/`
2. Установите через административную панель Bitrix
3. Модуль автоматически зарегистрирует сервисы

### Настройка инфоблока

[](#настройка-инфоблока)

Создайте инфоблок с кодом `product_reviews` и свойствами:

```
USER_NAME       (string)  - Имя пользователя
EVAL            (number)  - Оценка (1-5)
REVIEW          (text)    - Текст отзыва
CONTACT_DETAILS (string)  - Email/телефон
ELEMENT_ID      (number)  - ID товара
USER            (number)  - ID пользователя Bitrix
FILES           (file)    - Фотографии (множественное)

```

Быстрый старт
-------------

[](#быстрый-старт)

### Создание отзыва

[](#создание-отзыва)

```
use Beeralex\Reviews\Services\ReviewsService;
use Beeralex\Reviews\Dto\ReviewDTO;

$service = service(ReviewsService::class);

$dto = new ReviewDTO();
$dto->userName = 'Иван Петров';
$dto->eval = 5;
$dto->review = 'Отличный товар, рекомендую!';
$dto->contactDetails = 'ivan@example.com';
$dto->elementId = 123; // ID товара
$dto->userId = $USER->GetID() ?: null;

$result = $service->add($dto, $_FILES['files']);

if ($result->isSuccess()) {
    $elementId = $result->getData()['elementId'];
    echo "Отзыв создан с ID: {$elementId}";
} else {
    foreach ($result->getErrorMessages() as $error) {
        echo "Ошибка: {$error}\n";
    }
}
```

### Валидация данных

[](#валидация-данных)

ReviewDTO использует атрибуты для автоматической валидации:

```
$dto = new ReviewDTO();
$dto->userName = 'А'; // Слишком короткое имя
$dto->eval = 6;       // Вне диапазона 1-5
$dto->review = 'OK';  // Слишком короткий отзыв

if (!$dto->isValid()) {
    foreach ($dto->getErrors() as $error) {
        echo $error->getMessage() . "\n";
    }
}

// Вывод:
// Имя должно быть от 2 до 100 символов
// Максимальная оценка - 5
// Отзыв должен быть от 10 до 5000 символов
```

### Получение отзывов товара

[](#получение-отзывов-товара)

```
use Beeralex\Reviews\Repository\ReviewsRepository;

$repo = service(ReviewsRepository::class);

$reviews = $repo->all(
    filter: [
        'IBLOCK_SECTION_ID' => 123, // ID товара
        'ACTIVE' => 'Y'
    ],
    select: [
        'ID',
        'DATE_CREATE',
        'PROPERTY_USER_NAME',
        'PROPERTY_EVAL',
        'PROPERTY_REVIEW',
    ],
    order: ['ID' => 'DESC']
);

foreach ($reviews as $review) {
    echo "{$review['PROPERTY_USER_NAME_VALUE']}: ";
    echo str_repeat('⭐', $review['PROPERTY_EVAL_VALUE']);
    echo " - {$review['PROPERTY_REVIEW_VALUE']['TEXT']}\n";
}
```

REST API
--------

[](#rest-api)

Модуль интегрирован с `beeralex.api` через `ReviewController`.

### Получить список отзывов

[](#получить-список-отзывов)

```
fetch('/api/v1/review/index/?product_id=123&count=10')
  .then(res => res.json())
  .then(data => console.log('Отзывы:', data));
```

### Создать отзыв

[](#создать-отзыв)

```
const formData = new FormData();
formData.append('userName', 'Иван Петров');
formData.append('eval', 5);
formData.append('review', 'Отличный товар!');
formData.append('elementId', 123);
formData.append('files[]', fileInput.files[0]);

fetch('/api/v1/review/store/', {
  method: 'POST',
  body: formData
})
  .then(res => res.json())
  .then(data => {
    if (data.status === 'success') {
      console.log('Отзыв создан:', data.data.elementId);
    } else {
      console.error('Ошибки:', data.errors);
    }
  });
```

**Ответ (успех):**

```
{
  "status": "success",
  "data": {
    "elementId": 456
  }
}
```

**Ответ (ошибка):**

```
{
  "status": "error",
  "errors": [
    {
      "message": "Имя должно быть от 2 до 100 символов",
      "code": "review_create"
    }
  ]
}
```

Архитектура
-----------

[](#архитектура)

### Основные компоненты

[](#основные-компоненты)

```
ReviewsService              → Фасад для создания отзывов
├── ReviewCreatorService    → Логика создания, валидация
│   ├── UploadService       → Загрузка файлов
│   └── ReviewsRepository   → Работа с инфоблоком
└── ReviewDTO               → Валидация данных

```

### Сервисы

[](#сервисы)

**ReviewsService** — упрощенный интерфейс для добавления отзывов

**ReviewCreatorService** — реализация `CreatorContract`, содержит бизнес-логику

**UploadService** — реализация `FileUploaderContract`, загружает файлы через Bitrix CFile

**ReviewsRepository** — работа с инфоблоком отзывов (extends IblockRepository)

**SortingRepository** — статические варианты сортировки (новые/старые)

Расширение функционала
----------------------

[](#расширение-функционала)

### Добавление автоответа на отзыв

[](#добавление-автоответа-на-отзыв)

```
namespace App\Reviews\Services;

use Beeralex\Reviews\Services\ReviewCreatorService as BaseCreator;
use Beeralex\Reviews\Dto\ReviewDTO;
use Bitrix\Main\Result;

class ReviewCreatorService extends BaseCreator
{
    public function create(ReviewDTO $dto, array $files): Result
    {
        $result = parent::create($dto, $files);

        if ($result->isSuccess()) {
            $this->sendThankYouEmail($dto);
        }

        return $result;
    }

    protected function sendThankYouEmail(ReviewDTO $dto): void
    {
        \CEvent::Send('REVIEW_THANK_YOU', 's1', [
            'USER_NAME' => $dto->userName,
            'EMAIL' => $dto->contactDetails,
        ]);
    }
}
```

Зарегистрируйте в `/local/.settings_extra.php`:

```
use Beeralex\Reviews\Contracts\CreatorContract;
use App\Reviews\Services\ReviewCreatorService;

return [
    'services' => [
        'value' => [
            CreatorContract::class => [
                'constructor' => static function () {
                    return new ReviewCreatorService(
                        service(FileUploaderContract::class),
                        service(ReviewsRepository::class)
                    );
                }
            ],
        ]
    ]
];
```

### Добавление проверки на спам

[](#добавление-проверки-на-спам)

```
namespace App\Reviews\Services;

use Beeralex\Reviews\Services\ReviewCreatorService as BaseCreator;
use Beeralex\Reviews\Dto\ReviewDTO;
use Bitrix\Main\Result;
use Bitrix\Main\Error;

class ReviewCreatorService extends BaseCreator
{
    public function create(ReviewDTO $dto, array $files): Result
    {
        $result = new Result();

        if ($this->isSpam($dto)) {
            $result->addError(new Error('Отзыв отклонен как спам'));
            return $result;
        }

        return parent::create($dto, $files);
    }

    protected function isSpam(ReviewDTO $dto): bool
    {
        $spamWords = ['казино', 'кредит', 'займ'];
        $text = mb_strtolower($dto->review);

        foreach ($spamWords as $word) {
            if (str_contains($text, $word)) {
                return true;
            }
        }

        return false;
    }
}
```

### Уведомления через beeralex.notification

[](#уведомления-через-beeralexnotification)

```
namespace App\Reviews\Services;

use Beeralex\Reviews\Services\ReviewCreatorService as BaseCreator;
use Beeralex\Notification\NotificationManager;
use Beeralex\Notification\Dto\NotificationMessage;

class ReviewCreatorService extends BaseCreator
{
    public function create(ReviewDTO $dto, array $files): Result
    {
        $result = parent::create($dto, $files);

        if ($result->isSuccess()) {
            $this->notifyAdmin($dto, $result->getData()['elementId']);
        }

        return $result;
    }

    protected function notifyAdmin(ReviewDTO $dto, int $reviewId): void
    {
        $manager = new NotificationManager();

        $message = new NotificationMessage(
            eventName: 'NEW_REVIEW_MODERATION',
            fields: [
                'REVIEW_ID' => $reviewId,
                'USER_NAME' => $dto->userName,
                'RATING' => $dto->eval,
                'PRODUCT_ID' => $dto->elementId,
            ],
            userId: 1 // Администратор
        );

        $manager->notify($message);
    }
}
```

### Список отзывов товара

[](#список-отзывов-товара)

```
class ReviewListComponent extends CBitrixComponent
{
    public function executeComponent()
    {
        $repo = service(ReviewsRepository::class);

        $this->arResult['REVIEWS'] = $repo->all(
            filter: [
                'IBLOCK_SECTION_ID' => $this->arParams['PRODUCT_ID'],
                'ACTIVE' => 'Y'
            ],
            select: [
                'ID', 'DATE_CREATE',
                'PROPERTY_USER_NAME',
                'PROPERTY_EVAL',
                'PROPERTY_REVIEW',
                'PROPERTY_FILES',
            ],
            order: ['ID' => 'DESC']
        );

        // Статистика
        $evals = array_column($this->arResult['REVIEWS'], 'PROPERTY_EVAL_VALUE');
        $this->arResult['AVERAGE_RATING'] = !empty($evals)
            ? round(array_sum($evals) / count($evals), 1)
            : 0;
        $this->arResult['TOTAL_COUNT'] = count($this->arResult['REVIEWS']);

        $this->includeComponentTemplate();
    }
}
```

Модерация
---------

[](#модерация)

Все новые отзывы создаются с `ACTIVE='N'` и требуют одобрения.

### Автоматическая модерация через агент

[](#автоматическая-модерация-через-агент)

```
// В /local/php_interface/init.php
CAgent::AddAgent(
    "\\App\\Agents\\ReviewModerationAgent::moderate();",
    "", "N", 3600 // Каждый час
);

// Класс агента
namespace App\Agents;

class ReviewModerationAgent
{
    public static function moderate(): string
    {
        $repo = service(ReviewsRepository::class);

        // Одобрить отзывы 4-5 звезд от авторизованных
        $reviews = $repo->all([
            'ACTIVE' => 'N',
            '>=PROPERTY_EVAL' => 4,
            '!PROPERTY_USER' => false,
        ]);

        foreach ($reviews as $review) {
            $repo->update($review['ID'], ['ACTIVE' => 'Y']);
        }

        return "\\App\\Agents\\ReviewModerationAgent::moderate();";
    }
}
```

Зависимости
-----------

[](#зависимости)

- `beeralex.core` — Repository, FileService, AbstractRequestDto
- Bitrix/Main — Result, Error, Validation
- Bitrix/Iblock — работа с инфоблоками

Документация
------------

[](#документация)

Полная документация доступна в [docs/README.md](./docs/README.md)

Лицензия
--------

[](#лицензия)

Проприетарный модуль. © beeralex

###  Health Score

35

—

LowBetter than 79% of packages

Maintenance83

Actively maintained with recent releases

Popularity3

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~14 days

Total

9

Last Release

104d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/77bd3b8ad5192c498ba8d5a70ae80d7d73e8d13dda7989920a4fa47711fcb8c2?d=identicon)[BkycHblu-6oPwuK](/maintainers/BkycHblu-6oPwuK)

---

Top Contributors

[![BkycHblu-6oPwuK](https://avatars.githubusercontent.com/u/122775450?v=4)](https://github.com/BkycHblu-6oPwuK "BkycHblu-6oPwuK (19 commits)")

### Embed Badge

![Health badge](/badges/beeralex-beeralexreviews/health.svg)

```
[![Health](https://phpackages.com/badges/beeralex-beeralexreviews/health.svg)](https://phpackages.com/packages/beeralex-beeralexreviews)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
