Розробка класів на D7 API 1С-Бітрікс
D7 API — це не просто «новий API» поверх старого. Це інша філософія розробки: класи замість глобальних функцій, неймспейси замість CModule, Result-об'єкти замість bool та рядків помилок, Application як точка входу замість глобальних змінних. Розробка на D7 означає код, який не ламається при оновленні Бітрікс, тестується, перевикористовується та читається.
Базові концепції D7 API
Application — синглтон, точка входу:
$app = \Bitrix\Main\Application::getInstance();
$connection = $app->getConnection(); // підключення до БД
$request = $app->getContext()->getRequest(); // HTTP-запит
$server = $app->getContext()->getServer(); // дані сервера
Result-об'єкти. Будь-який метод, який може завершитися з помилкою, повертає нащадок \Bitrix\Main\Result:
class MyServiceResult extends \Bitrix\Main\Result
{
private ?array $data = null;
public function setData(array $data): void
{
$this->data = $data;
}
public function getData(): ?array
{
return $this->data;
}
}
// Використання
$result = new MyServiceResult();
if ($someConditionFailed) {
$result->addError(new \Bitrix\Main\Error('Немає даних для обробки', 'NO_DATA'));
return $result;
}
$result->setData($processedData);
return $result;
// Код, що викликає
$result = MyService::process($input);
if (!$result->isSuccess()) {
foreach ($result->getErrors() as $error) {
echo $error->getMessage(); // Немає даних для обробки
}
}
Це усуває клас помилок «функція повернула false, але чому — невідомо».
Структура сервісного класу
Бізнес-логіку виносимо у сервіси — класи з чіткою відповідальністю:
namespace MyProject\Services;
use Bitrix\Main\Result;
use Bitrix\Main\Error;
use MyProject\Storage\OrderLogTable;
class OrderService
{
public function __construct(
private readonly int $orderId
) {}
public function changeStatus(string $newStatus): Result
{
$result = new Result();
$allowedStatuses = ['PENDING', 'PROCESSING', 'SHIPPED', 'DELIVERED', 'CANCELLED'];
if (!in_array($newStatus, $allowedStatuses, true)) {
$result->addError(new Error("Недопустимий статус: {$newStatus}", 'INVALID_STATUS'));
return $result;
}
$order = \Bitrix\Sale\Order::load($this->orderId);
if (!$order) {
$result->addError(new Error("Замовлення #{$this->orderId} не знайдено", 'ORDER_NOT_FOUND'));
return $result;
}
$saveResult = $order->setField('STATUS_ID', $newStatus);
if (!$saveResult->isSuccess()) {
$result->addErrors($saveResult->getErrors());
return $result;
}
$order->save();
OrderLogTable::add([
'ORDER_ID' => $this->orderId,
'ACTION' => "STATUS_CHANGED_TO_{$newStatus}",
]);
return $result;
}
}
Робота з HTTP-запитом через D7
Старий спосіб — $_POST['field']. D7-спосіб:
$request = \Bitrix\Main\Application::getInstance()->getContext()->getRequest();
$field = $request->getPost('field'); // POST-параметр
$param = $request->getQuery('param'); // GET-параметр
$file = $request->getFile('upload'); // завантажений файл
$isAjax = $request->isAjaxRequest();
$isPost = $request->isPost();
Об'єкт Request фільтрує вхідні дані та надає типізований доступ. Це не «безпечніше магічно», але явно показує джерело даних.
Сервіс-локатор та DI
У Бітрікс немає повноцінного DI-контейнера, але є сервіс-локатор:
// Реєстрація сервісу (в init.php або в методі модуля)
\Bitrix\Main\DI\ServiceLocator::getInstance()->addInstanceLazy(
'myproject.order.service',
static function() {
return new \MyProject\Services\OrderNotificationService(
new \MyProject\Services\MailSender(),
new \MyProject\Services\SmsGateway()
);
}
);
// Отримання сервісу будь-де в коді
$notifier = \Bitrix\Main\DI\ServiceLocator::getInstance()
->get('myproject.order.service');
Відмова від глобальних змінних та статичних викликів робить код тестованим.
Кеш D7
$cache = \Bitrix\Main\Data\Cache::createInstance();
$cacheKey = md5('product_list_' . $categoryId);
if ($cache->initCache(3600, $cacheKey, '/myproject/products/')) {
$data = $cache->getVars();
} else {
$data = $this->loadFromDatabase($categoryId);
$cache->startDataCache();
$cache->endDataCache($data);
}
Тегований кеш для інвалідації групи записів:
$taggedCache = \Bitrix\Main\Application::getInstance()->getTaggedCache();
$taggedCache->startTagCache('/myproject/products/');
$taggedCache->registerTag('my_product_' . $productId);
$taggedCache->endTagCache();
// Інвалідація при зміні товару
$taggedCache->clearByTag('my_product_' . $productId);
Робота з файлами через D7
use Bitrix\Main\IO\File;
use Bitrix\Main\IO\Directory;
// Створення директорії
Directory::createDirectory('/path/to/dir');
// Робота з файлом
$file = new File('/path/to/file.txt');
$file->putContents('content');
$content = $file->getContents();
$exists = $file->isExists();
Типові паттерни при розробці сервісних класів
Repository — клас для роботи зі сховищем даних, ізолює ORM-код від бізнес-логіки.
Factory — фабрика об'єктів за типом або параметрами.
Strategy — вибір алгоритму в рантаймі (наприклад, різні способи розрахунку знижки залежно від типу клієнта).
Ці паттерни не прив'язані до Бітрікс — це стандартний PHP. D7 просто дає достатньо інструментів, щоб їх застосовувати.
Терміни
| Завдання | Термін |
|---|---|
| Набір сервісних класів для окремої функціональності (5–10 класів) | 1–2 тижні |
| Повний сервісний прошарок для модуля (репозиторії, сервіси, фабрики, Result-об'єкти) | 3–5 тижнів |
| Написання юніт-тестів для готових класів | +30–50% до термінів розробки |
Код на D7 API живе довго. Його можна оновлювати по частинах, тестувати, перевикористовувати в інших проектах. Це окупається вже на першому значному рефакторингу або при передачі проекту новому розробнику.







