Bitrixapigen — пакет для генерации серверной части приложения (контроллеры + дто + роутер) на основе OpenApi контракта на битриксе.
composer require webpractik/bitrixapigen --dev
Если на проекте еще настроен роутинг, то сделайте это.
https://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=43&CHAPTER_ID=013764
Обратите внимание на подключение файлов routes.php. Это кастомный файл, который будет присутствовать в модуле сгенерированном пакетом, поэтому нужно реализовать подключение роутов из routes.php.
<?php
use Bitrix\Main\ModuleManager;
use Bitrix\Main\Routing\RoutingConfigurator;
require_once $_SERVER['DOCUMENT_ROOT'] . '/../vendor/autoload.php';
$getRoutePaths = static function (): array {
foreach (ModuleManager::getInstalledModules() as $module) {
$route = $_SERVER['DOCUMENT_ROOT'] . '/local/modules/' . $module['ID'] . '/routes.php';
if (file_exists($route)) {
$routes[] = $route;
}
}
return $routes ?? [];
};
return static function (RoutingConfigurator $configurator) use ($getRoutePaths) {
foreach ($getRoutePaths() as $route) {
$callback = include $route;
if ($callback instanceof Closure) {
$callback($configurator);
}
}
};
'routing' => [
'value' => [
'config' => [
'api.php',
],
],
],
- Подготовьте OpenAPI-спецификацию (JSON или YAML)
📝 Все данные передаваемые в телах запросов должны быть описаны через схемы (
schema
) в OpenAPI-спецификации. Именно на их основе происходит генерация соответствующих DTO, коллекций и корректная передача аргументов в UseCase.
Контракт, разбитый на несколько файлов, должен целиком находиться в каталоге (или его подкаталогах), содержащем корневой файл.
Ответы могут быть только типа application/json
.
✅ Правильно: Запрос и ответ должны быть описаны отдельными схемами.
/api/user/register/:
post:
tags:
- User
summary: User registration
description: Регистрация пользователя
operationId: userRegistration
requestBody:
description: Обязательные поля
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UserRegisterFields'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/UserRegisterResponse'
❌ Неправильно:
/api/user/register/:
post:
tags:
- User
summary: User registration
description: Регистрация пользователя
operationId: userRegistration
requestBody:
description: Обязательные поля
required: true
content:
application/json:
schema:
type: object
properties:
EMAIL:
type: string
PASSWORD:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
ID:
type: number
example: 111
☑️ Исключение: массив объектов
/api/user/createWithList:
post:
tags:
- User
summary: Creates list of users with given input array
description: Creates list of users with given input array
operationId: createUsersWithListInput
requestBody:
content:
application/json:
schema:
type: array
minItems: 5
items:
$ref: '#/components/schemas/User'
/api/user/{userId}/uploadImage:
post:
tags:
- User
summary: uploads an image
description: ''
operationId: uploadFile
parameters:
- name: userId
in: path
description: ID of user to update
required: true
schema:
type: integer
format: int64
- name: additionalMetadata
in: query
description: Additional Metadata
required: false
schema:
type: string
requestBody:
content:
application/octet-stream:
schema:
type: string
format: binary
- Выполните генерацию:
php vendor/bin/bitrixapigen generate --openapi-file path/to/openapi.yaml --locale ru
или кратко:
php vendor/bin/bitrixapigen generate -o path/to/openapi.yaml -l ru
🟡 Параметр --openapi-file (или -o) — обязателен
🟡 Параметр --locale (или -l) — язык для сообщений валидатора по стандату BCP 47 не обязателен, по умолчанию будет ru
- Установите модуль:
- через административную панель Bitrix (
/bitrix/admin/partner_modules.php
) - или через миграцию/скрипт
- через административную панель Bitrix (
⚠️ После генерации необходимо обязательно подключить модульwebpractik.bitrixgen
в самом конце файлаlocal/php_interface/init.php
, чтобы он корректно зарегистрировал свои контроллеры и роуты.
local/modules/webpractik.bitrixgen/
├── lib/
│ ├── Controllers/
│ ├── Dto/
│ │ └── Collection/
│ ├── Exception/
│ ├── Interfaces/ ← интерфейсы, которые имплементируются в UseCase-классах (один роут - один интерфейс)
│ ├── Response/
│ └── UseCase/ ← UseCase-классы (один роут - один интерфейс - UseCase класс)
├── .settings.php ← регистрация сервисов в DI Bitrix
├── include.php ← точка подключения модуля
├── routes.php ← кастомный файл с роутами
Для каждого роута генерируется интерфейс, например, Interfaces/IUploadPetFormWithFiles.php
и
класс-заглушка UseCase/UploadPetFormWithFiles.php
, который реализует интерфейс IUploadPetFormWithFiles
.
В файле .settings.php
UploadPetFormWithFiles регистрируется как реализация для интерфейса.
Контроллеры получают входные данные, инициализируют DTO, коллекции или другие переменные и вызывают реализацию интерфейса UseCase через ServiceLocator
:
$useCase = \Bitrix\Main\DI\ServiceLocator::getInstance()->get('webpractik.bitrixgen.uploadPetFormWithFiles');
return new \Bitrix\Main\Engine\Response\Json(
$useCase->process($petId, $dto)
);
Модуль webpractik.bitrixgen
не должен редактироваться вручную. Любые правки в нем будут утеряны после перегенерации этого модуля.
Предполагается, что вся логика роута будет размещена в соответствующем UseCase.
-
Создайте свой модуль, например, my.module
-
Создайте в нем реализацию интерфейса для соответствующего роута:
namespace My\Module\UseCase;
use Webpractik\Bitrixgen\Interfaces\IUploadPetFormWithFiles;
class UploadPetFormWithFiles implements IUploadPetFormWithFiles
{
public function process(int $petId, \Webpractik\Bitrixgen\Dto\PetFormUpload $dto): ?\Webpractik\Bitrixgen\Dto\Pet
{
return new \Webpractik\Bitrixgen\Dto\Pet();
}
}
- Зарегистрируйте реализацию в
.settings.php
модуляmy.module
:
<?php
namespace My\Module;
use Bitrix\Main\DI\ServiceLocator;
$serviceLocator = ServiceLocator::getInstance();
$serviceValue = [];
if ($serviceLocator->has('webpractik.bitrixgen.uploadPetFormWithFiles')) {
if (!in_array(\Webpractik\Bitrixgen\Interfaces\IUploadPetFormWithFiles::class, class_implements($serviceLocator->get('webpractik.bitrixgen.uploadPetFormWithFiles')))) {
$serviceValue['webpractik.bitrixgen.uploadPetFormWithFiles'] = [\My\Module\UseCase\UploadPetFormWithFiles::class];
}
}
if (!$serviceLocator->has('webpractik.bitrixgen.uploadPetFormWithFiles')) {
$serviceValue['webpractik.bitrixgen.uploadPetFormWithFiles'] = ['className' => \My\Module\UseCase\UploadPetFormWithFiles::class];
}
return ['services' => ['value' => $serviceValue]];
- Подключите свой модуль
my.module
в файлеlocal/php_interface/init.php
перед подключением модуляwebpractik.bitrixgen
:
\Bitrix\Main\Loader::includeModule('my.module');
\Bitrix\Main\Loader::includeModule('webpractik.bitrixgen'); // строго в конце!
Контроллер автоматически передаёт в метод process()
:
$dto
или$collection
— еслиrequestBody
с типомapplication/json
илиmultipart/form-data
string $octetStreamRawContent
— если типrequestBody
—application/octet-stream
array $queryParameters
— если в OpenAPI-спецификации заданы query-параметры- path-параметры — передаются как отдельные переменные (например,
int $petId
)
Валидируются все входные данные, которые описаны согласно разделу Требования к OpenAPI-контракту, за исключением бинарного файла, переданного в формате application/octet-stream
.
В случае ошибок валидации возвращается HTTP статус 422 и структура ответа следующего вида:
{
"message": "Валидация не пройдена",
"errors": [
{
"field": "[1][username]",
"message": "Это поле отсутствует."
}
]
}
- PHP 8.1+
- Bitrix Framework (D7)
- OpenAPI 3.0+
- Генерация ошибок и логика их обработки в контроллере (важно, чтобы возвращались только описанные схемой статусы)
- Генерация тестов
- Авторизация в роутах
- Привести генерируемый код в соответствие со стандартом PSR