{"id":25858722,"url":"https://github.com/webpractik/bitrixapigen","last_synced_at":"2026-05-08T22:35:46.658Z","repository":{"id":278708689,"uuid":"936509458","full_name":"webpractik/bitrixapigen","owner":"webpractik","description":"Bitrixapigen - пакет для реализации стратегии ContractFirst и кодогенерации на бекенде. Генерируются роутеры, контроллеры, валидаторы, DTO.","archived":false,"fork":false,"pushed_at":"2025-07-29T15:41:40.000Z","size":310,"stargazers_count":10,"open_issues_count":7,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-10-05T02:21:42.175Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/webpractik.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-02-21T07:58:21.000Z","updated_at":"2025-07-29T15:41:43.000Z","dependencies_parsed_at":"2025-02-21T09:27:51.111Z","dependency_job_id":"6c750611-c74f-4d28-ae61-53474b7cb91d","html_url":"https://github.com/webpractik/bitrixapigen","commit_stats":null,"previous_names":["webpractik/bitrixapigen"],"tags_count":27,"template":false,"template_full_name":null,"purl":"pkg:github/webpractik/bitrixapigen","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webpractik%2Fbitrixapigen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webpractik%2Fbitrixapigen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webpractik%2Fbitrixapigen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webpractik%2Fbitrixapigen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/webpractik","download_url":"https://codeload.github.com/webpractik/bitrixapigen/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webpractik%2Fbitrixapigen/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32800476,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-08T08:22:46.396Z","status":"ssl_error","status_checked_at":"2026-05-08T08:22:45.650Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-01T20:30:00.239Z","updated_at":"2026-05-08T22:35:46.652Z","avatar_url":"https://github.com/webpractik.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Bitrixapigen ❤️ ContractFirst\n\n__Bitrixapigen__ — пакет для генерации серверной части приложения (контроллеры + дто + роутер) на основе OpenApi контракта на битриксе.\n\n---\n\n## ⚙️ Установка\n\n``` shell\ncomposer require webpractik/bitrixapigen --dev\n```\n\n---\n\n## 🔧 Настройка роутинга Bitrix D7\n\nЕсли на проекте еще настроен роутинг, то сделайте это.\n\n### Шаг 1: Настройте роутинг по документации\n▶️ Официальная документация Bitrix:  \n[https://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=43\u0026CHAPTER_ID=013764](https://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=43\u0026CHAPTER_ID=013764)\n\n### Шаг 2: *local/routes/api.php*\n\nОбратите внимание на подключение файлов routes.php. Это кастомный файл, который будет присутствовать в модуле сгенерированном пакетом,\nпоэтому нужно реализовать подключение роутов из routes.php.\n\n```php\n\u003c?php\n\nuse Bitrix\\Main\\ModuleManager;\nuse Bitrix\\Main\\Routing\\RoutingConfigurator;\n\nrequire_once $_SERVER['DOCUMENT_ROOT'] . '/../vendor/autoload.php';\n\n$getRoutePaths = static function (): array {\n    foreach (ModuleManager::getInstalledModules() as $module) {\n        $route = $_SERVER['DOCUMENT_ROOT'] . '/local/modules/' . $module['ID'] . '/routes.php';\n        if (file_exists($route)) {\n            $routes[] = $route;\n        }\n    }\n\n    return $routes ?? [];\n};\n\nreturn static function (RoutingConfigurator $configurator) use ($getRoutePaths) {\n    foreach ($getRoutePaths() as $route) {\n        $callback = include $route;\n        if ($callback instanceof Closure) {\n            $callback($configurator);\n        }\n    }\n};\n```\n\n### Шаг 3: Проверьте, что файл `local/routes/api.php` подключен в `.settings.php`\n\n```php\n'routing' =\u003e [\n    'value' =\u003e [\n        'config' =\u003e [\n             'api.php',\n        ],\n    ],\n],\n```\n\n---\n\n## 🚀 Быстрый старт\n\n1. Подготовьте OpenAPI-спецификацию (JSON или YAML)\n\u003e 📝 Все данные передаваемые в телах запросов должны быть описаны через схемы (`schema`) в OpenAPI-спецификации. Именно на их основе происходит генерация соответствующих DTO, коллекций и корректная передача аргументов в UseCase.\n\n### Требования к OpenAPI-контракту\n\nКонтракт, разбитый на несколько файлов, должен целиком находиться в каталоге (или его подкаталогах), содержащем корневой файл.\n\nОтветы могут быть только типа `application/json`.\n\n ✅ Правильно:\nЗапрос и ответ должны быть описаны отдельными схемами.\n\n```yaml\n/api/user/register/:\n  post:\n    tags:\n      - User\n    summary: User registration\n    description: Регистрация пользователя\n    operationId: userRegistration\n    requestBody:\n      description: Обязательные поля\n      required: true\n      content:\n        application/json:\n          schema:\n            $ref: '#/components/schemas/UserRegisterFields'\n    responses:\n      '200':\n        description: OK\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/UserRegisterResponse'\n```\n\n❌ Неправильно:\n```yaml\n/api/user/register/:\n  post:\n    tags:\n      - User\n    summary: User registration\n    description: Регистрация пользователя\n    operationId: userRegistration\n    requestBody:\n      description: Обязательные поля\n      required: true\n      content:\n        application/json:\n          schema:\n            type: object\n            properties:\n              EMAIL:\n                type: string\n              PASSWORD:\n                type: string\n    responses:\n      '200':\n        description: OK\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                ID:\n                  type: number\n                  example: 111\n```\n\n☑️ Исключение: массив объектов\n```yaml\n/api/user/createWithList:\n  post:\n    tags:\n      - User\n    summary: Creates list of users with given input array\n    description: Creates list of users with given input array\n    operationId: createUsersWithListInput\n    requestBody:\n      content:\n        application/json:\n          schema:\n            type: array\n            minItems: 5\n            items:\n              $ref: '#/components/schemas/User'\n```\n\n⚠️ Бинарный файл\nВнимание! С файлом на текущий момент работает только так, описание через схему ломает генерацию (баг):\n\n```yaml\n/api/user/{userId}/uploadImage:\n  post:\n    tags:\n      - User\n    summary: uploads an image\n    description: ''\n    operationId: uploadFile\n    parameters:\n      - name: userId\n        in: path\n        description: ID of user to update\n        required: true\n        schema:\n          type: integer\n          format: int64\n      - name: additionalMetadata\n        in: query\n        description: Additional Metadata\n        required: false\n        schema:\n          type: string\n    requestBody:\n      content:\n        application/octet-stream:\n          schema:\n            type: string\n            format: binary\n```\n4. Выполните генерацию:\n\n*php vendor/bin/bitrixapigen generate --openapi-file path/to/openapi.yaml --locale ru*  \nили кратко:  \n*php vendor/bin/bitrixapigen generate -o path/to/openapi.yaml -l ru*\n\n\u003e 🟡 Параметр *--openapi-file* (или *-o*) — **обязателен**\n\n\u003e 🟡 Параметр *--locale* (или *-l*) — язык для сообщений валидатора по стандату BCP 47 **не обязателен, по умолчанию будет ru**\n\n3. Установите модуль:\n    - через административную панель Bitrix (`/bitrix/admin/partner_modules.php`)\n    - или через миграцию/скрипт\n\n---\n\n## 📁 Структура сгенерированного модуля\n\n\u003e ⚠️ После генерации необходимо обязательно подключить модуль `webpractik.bitrixgen` в самом конце файла `local/php_interface/init.php`, чтобы он корректно зарегистрировал свои контроллеры и роуты.\n\n```\nlocal/modules/webpractik.bitrixgen/\n├── lib/\n│   ├── Controllers/\n│   ├── Dto/\n│   │   └── Collection/\n│   ├── Exception/\n│   ├── Interfaces/            ← интерфейсы, которые имплементируются в UseCase-классах (один роут - один интерфейс)\n│   ├── Response/\n│   └── UseCase/               ← UseCase-классы (один роут - один интерфейс - UseCase класс)\n├── .settings.php              ← регистрация сервисов в DI Bitrix\n├── include.php                ← точка подключения модуля\n├── routes.php                 ← кастомный файл с роутами\n```\n\n---\n\n## 🧠 Архитектура\n\nДля каждого роута генерируется интерфейс, например, `Interfaces/IUploadPetFormWithFiles.php` и\nкласс-заглушка `UseCase/UploadPetFormWithFiles.php`, который реализует интерфейс `IUploadPetFormWithFiles`.\n\nВ файле `.settings.php` UploadPetFormWithFiles регистрируется как реализация для интерфейса.\n\nКонтроллеры получают входные данные, инициализируют DTO, коллекции или другие переменные и вызывают реализацию интерфейса UseCase через `ServiceLocator`:\n\n```php\n$useCase = \\Bitrix\\Main\\DI\\ServiceLocator::getInstance()-\u003eget('webpractik.bitrixgen.uploadPetFormWithFiles');\nreturn new \\Bitrix\\Main\\Engine\\Response\\Json(\n    $useCase-\u003eprocess($petId, $dto)\n);\n```\nМодуль `webpractik.bitrixgen` **не должен редактироваться вручную**. Любые правки в нем будут утеряны после перегенерации этого модуля.\n\n---\n\n## 🧩 Как реализовать функционал роутов\n\nПредполагается, что вся логика роута будет размещена в соответствующем UseCase.\n\n1. Создайте свой модуль, например, my.module\n\n2. Создайте в нем реализацию интерфейса для соответствующего роута:\n\n```php\nnamespace My\\Module\\UseCase;\n\nuse Webpractik\\Bitrixgen\\Interfaces\\IUploadPetFormWithFiles;\n\nclass UploadPetFormWithFiles implements IUploadPetFormWithFiles\n{\n    public function process(int $petId, \\Webpractik\\Bitrixgen\\Dto\\PetFormUpload $dto): ?\\Webpractik\\Bitrixgen\\Dto\\Pet\n    {\n        return new \\Webpractik\\Bitrixgen\\Dto\\Pet();\n    }\n}\n```\n\n2. Зарегистрируйте реализацию в `.settings.php` модуля `my.module`:\n\n```php\n\u003c?php\n\nnamespace My\\Module;\n\nuse Bitrix\\Main\\DI\\ServiceLocator;\n\n$serviceLocator = ServiceLocator::getInstance();\n$serviceValue = [];\n\nif ($serviceLocator-\u003ehas('webpractik.bitrixgen.uploadPetFormWithFiles')) {\n    if (!in_array(\\Webpractik\\Bitrixgen\\Interfaces\\IUploadPetFormWithFiles::class, class_implements($serviceLocator-\u003eget('webpractik.bitrixgen.uploadPetFormWithFiles')))) {\n        $serviceValue['webpractik.bitrixgen.uploadPetFormWithFiles'] = [\\My\\Module\\UseCase\\UploadPetFormWithFiles::class];\n    }\n}\n\nif (!$serviceLocator-\u003ehas('webpractik.bitrixgen.uploadPetFormWithFiles')) {\n    $serviceValue['webpractik.bitrixgen.uploadPetFormWithFiles'] = ['className' =\u003e \\My\\Module\\UseCase\\UploadPetFormWithFiles::class];\n}\n\nreturn ['services' =\u003e ['value' =\u003e $serviceValue]];\n```\n\n4. Подключите свой модуль `my.module` в файле `local/php_interface/init.php` перед подключением модуля `webpractik.bitrixgen`:\n\n```php\n\\Bitrix\\Main\\Loader::includeModule('my.module');\n\n\\Bitrix\\Main\\Loader::includeModule('webpractik.bitrixgen'); // строго в конце!\n```\n\n---\n\n## 📥 Что передаёт контроллер в UseCase\n\nКонтроллер автоматически передаёт в метод `process()`:\n\n- **`$dto` или `$collection`** — если `requestBody` с типом `application/json` или `multipart/form-data`\n- **`string $octetStreamRawContent`** — если тип `requestBody` — `application/octet-stream`\n- **`array $queryParameters`** — если в OpenAPI-спецификации заданы query-параметры\n- **path-параметры** — передаются как отдельные переменные (например, `int $petId`)\n\n---\n\n## ✅ Валидация\n\nВалидируются все входные данные, которые описаны согласно разделу [Требования к OpenAPI-контракту](#требования-к-openapi-контракту), за исключением бинарного файла, переданного в формате `application/octet-stream`.\n\nВ случае ошибок валидации возвращается HTTP статус **422** и структура ответа следующего вида:\n\n```json\n{\n    \"message\": \"Валидация не пройдена\",\n    \"errors\": [\n        {\n            \"field\": \"[1][username]\",\n            \"message\": \"Это поле отсутствует.\"\n        }\n    ]\n}\n```\n\n## 🛠 Требования\n\n- PHP 8.1+\n- Bitrix Framework (D7)\n- OpenAPI 3.0+\n\n---\n\n## Roadmap\n\n- [ ] Генерация ошибок и логика их обработки в контроллере (важно, чтобы возвращались только описанные схемой статусы)\n- [ ] Генерация тестов\n- [ ] Авторизация в роутах\n- [ ] Привести генерируемый код в соответствие со стандартом PSR\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebpractik%2Fbitrixapigen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwebpractik%2Fbitrixapigen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebpractik%2Fbitrixapigen/lists"}