{"id":18513686,"url":"https://github.com/proklung/bitrix.core.symfony","last_synced_at":"2026-03-06T19:35:49.128Z","repository":{"id":57045095,"uuid":"368752977","full_name":"ProklUng/bitrix.core.symfony","owner":"ProklUng","description":"Базовый функционал для внедрения Symfony в Битрикс","archived":false,"fork":false,"pushed_at":"2023-05-10T07:03:55.000Z","size":141,"stargazers_count":8,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-05-03T19:13:52.112Z","etag":null,"topics":["bitrix","bitrix-symfony","php7"],"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/ProklUng.png","metadata":{"files":{"readme":"readme.MD","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-05-19T05:23:01.000Z","updated_at":"2023-11-17T11:32:42.000Z","dependencies_parsed_at":"2022-08-24T04:50:44.616Z","dependency_job_id":null,"html_url":"https://github.com/ProklUng/bitrix.core.symfony","commit_stats":null,"previous_names":[],"tags_count":70,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProklUng%2Fbitrix.core.symfony","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProklUng%2Fbitrix.core.symfony/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProklUng%2Fbitrix.core.symfony/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProklUng%2Fbitrix.core.symfony/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ProklUng","download_url":"https://codeload.github.com/ProklUng/bitrix.core.symfony/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223367987,"owners_count":17134230,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["bitrix","bitrix-symfony","php7"],"created_at":"2024-11-06T15:40:14.772Z","updated_at":"2026-03-06T19:35:49.065Z","avatar_url":"https://github.com/ProklUng.png","language":"PHP","readme":"# Базовый функционал для внедрения Symfony в Битрикс\n\n## Установка\n\ncomposer.json:\n\n```json\n    \"repositories\": [\n        {\n            \"type\": \"git\",\n            \"url\": \"https://github.com/proklung/bitrix.core.symfony\"\n        }\n    ]\n```\n\n```bash\ncomposer require proklung/bitrix-core-symfony\n```\n\n## Инициализация\n\nВ `init.php`:\n\n```php\nuse Prokl\\ServiceProvider\\ServiceProvider;\n\n$serviceProvider = new ServiceProvider('local/configs/services.yaml');\n\n```\n\nДля обеспечения \"преемственности\" (похожести) с оригиналом можно задать путь к файлу конфигурации (скажем, `bundles.php`)\nбандлов вторым (необязательным) параметром конструктора.\n\n#### Переменные среды\n\nПредполагается, что переменные среды к моменту инициализации контейнера уже загружены тем или иным способом.\n\nЗначимые переменные среды: \n\n- `DEBUG` (булево значение - режим отладки), `APP_DEBUG` - алиас `DEBUG`, но с большим приоритетом\n(если одновременно присустствуют `DEBUG` и `APP_DEBUG`, то в дело пойдет значение `APP_DEBUG`).\n\n- `APP_ENV` - код окружения. Если код не задан, то будет проинтерпретировано значение `DEBUG` в смысле - если в режиме отладки,\nто окружение `dev`, иначе `prod`.\n\nЕсли переменные среды не заданы, то с помощью класса `Prokl\\ServiceProvider\\LoadEnvironment` их можно загрузить.\n\nСкажем, в `init.php`, перед инициализацией контейнера:\n\n```php\n    // Параметр конструктора - путь, где лежат файлы .env\n    $loader = new \\Prokl\\ServiceProvider\\LoadEnvironment($_SERVER['DOCUMENT_ROOT'] . '/../..');\n    $loader-\u003eload(); // Загрузка $_ENV\n    $loader-\u003eprocess(); // Обработка переменных\n```\n\n## Конфигурирование\n\n1) Опция `compile.container` в подтягиваемом конфиге - компилировать ли контейнер в файл. Если не задана, то \"нет, не компилировать\".\nИмеет смысл для окружения, не равного \"dev\". Т.е. опция управляет дампированием контейнера на проде.\n\nМесто, где хранятся дампы контейнеров: `\u003cзначение переменной контейнера kernel.cache_dir\u003e/\u003cSITE_ID\u003e/containers` \n\n#### Пути к кэшу и логам\n\nОпределяются классом `AppKernel`. По умолчанию:\n\n- путь к кэшу (`kernel.cache_dir`) - `/bitrix/cache`\n- путь к логам (`kernel.logs_dir`) - `'/../../logs'` (два уровня выше DOCUMENT_ROOT - особенности используемой\nсборки Битрикс)\n\nЧтобы это изменить нужно отнаследоваться от класса `AppKernel` и переопределить несколько переменных:\n\n```php\nuse Prokl\\ServiceProvider\\Services\\AppKernel;\n\nclass MyKernel extends AppKernel\n{\n   protected $cacheDir = '/bitrix/cache/mycache';\n    \n   protected $logDir = '/logs-saver';\n}\n```\n(второй вариант - отнаследоваться от `AppKernel` и переопределить методы `getCacheDir` и `getLogDir`).\n\nИзменить через наследование класс ядра:\n\n```php\nclass MyServiceProvider extends ServiceProvider\n{\n    protected $kernelServiceClass = MyKernel::class;\n\n    protected $cacheDir = '/bitrix/cache/mycache';\n\n}\n```\n\nВторой вариант - отнаследоваться от `ServiceProvider` и заменить метод `getPathCacheDirectory` своей логикой.\n\n## Поддержка бандлов\n\nФайл конфигурации - `/config/standalone_bundles.php`. Этот путь можно изменить через конструктор.\n\nПапка, где лежат конфигурации - `/local/configs`. Конфигурации бандлов - `/local/configs/packages`. \n\n#### Проблема с приватными сервисами\n\nСогласно концепции Symfony все сервисы (в идеале) должны быть приватными и инжектиться. Но в кастомном случае \nчасто нужно получать их через хелпер-сервис-локатор. Для превращения нужных сервисов в публичные предлагается\nтакое решение. В общем разделе параметров контейнера появилась опция `publicable_services`:\n\n```yaml\nparameters:\n  publicable_services:\n    - 'snc_redis.default'\n```\n\nПосле компиляции контейнера приватный сервис `snc_redis.default` станет публичным.\n\n## Сепаратные микро-контейнеры\n\nОтдельные контейнеры - со своим конфигом, полностью изолированные (для модулей и т.п.).\n\n```php\nuse Symfony\\Component\\DependencyInjection\\ContainerBuilder;\nuse Prokl\\ServiceProvider\\Micro\\AbstractStandaloneServiceProvider;\nuse Prokl\\ServiceProvider\\Micro\\ExampleAppKernel;\n\nclass ExampleMicroServiceProvider extends AbstractStandaloneServiceProvider\n{\n    /**\n     * @var ContainerBuilder $containerBuilder Контейнер.\n     */\n    protected static $containerBuilder;\n\n    /**\n     * @var string $pathBundlesConfig Путь к конфигурации бандлов.\n     */\n    protected $pathBundlesConfig = '/src/Micro/example.config/standalone_bundles.php';\n\n    /**\n     * @var string $configDir Папка, где лежат конфиги.\n     */\n    protected $configDir = '/src/Micro/example.config/example.config/example.yaml';\n\n     /**\n     * @var string $kernelServiceClass Класс, реализующий сервис kernel.\n     * Нужен для того, чтобы экземпляры контейнеров в kernel сервисе не перемешивались.\n     */\n    protected $kernelServiceClass = ExampleAppKernel::class;\n\n}\n```\n\nПример класса `ExampleAppKernel`:\n\n```php\nuse Prokl\\ServiceProvider\\Micro\\AbstractKernel;\n\nclass ExampleAppKernel extends AbstractKernel\n{\n    protected static $kernelContainer;\n}\n```\n\nГде надо - инициализация:\n\n```php\n$micro = new ExampleMicroServiceProvider('src/SymfonyDI/Micro/example.config/example.yaml');\n```\n\nХэлпер `container` заточен под работу с микро-сервис-провайдерами:\n\n```php\nvar_dump(container($micro)-\u003egetParameter('example'));\n```\n\n## Автозапуск сервисов\n\nЧтобы сервис запустился автоматически после инициализации контейнера, он должен быть помечен тэгом `service.bootstrap`.\n\n```yaml\n  app.options:\n    class: Prokl\\Services\\AppOptions\n    arguments: ['%kernel.environment%', '@parameter_bag']\n    tags: ['service.bootstrap']\n```\n\nПоддерживается приоритет запуска. Тогда надо так:\n\n```yaml\n  app.options:\n    class: Local\\Services\\AppOptions\n    arguments: ['%kernel.environment%', '@parameter_bag']\n    tags: \n      - { name: 'service.bootstrap', priority: 100 }\n```\n\nСервис с приоритетом 100 запустится раньше сервиса с приоритетом 200.\n\n## Автоматическая подвязка на события Битрикс\n\nТэг: `bitrix.events.init`.\n\n1) `event` - название события.\n2) `method` - метод-обработчик в сервисе\n3) `module` - модуль события\n4) `sort` - сортировка\n\n```yaml\n  admin_entity_edit.event_init:\n    class: Local\\Bitrix\\PsModuleInitializer\n    tags:\n      - { name: bitrix.events.init, module: ps.d7, event: onGetEntityList, method: registerEntities, sort: 0 }\n```\n\n## Автоматическое подхватывание расширений Twig\n\nТэг `twig.extension`.\n\n```yaml\n  service.twig.parameter:\n    class: Prokl\\Bundles\\ParameterBundle\\Twig\\ParameterExtension\n    public: true\n    arguments:\n      - '@service.parameter'\n    tags:\n      - { name: twig.extension }\n```\n\n## Сервисы по умолчанию\n\nАвтоматом регистрируются сервисы:\n\n- `service_container` (и alias) - сервис-контейнер целиком\n- `app.request` - конвертор глобалов в Request\n- синонимы сервиса `kernel`\n- `delegated_container_manipulator` - манипулятор делегированными контейнерами.\n- `bitrix.request.instance` - Экземпляр битриксового Request\n- `bitrix.response.instance` - Экземпляр битриксового Response\n- `bitrix.request` - Symfony Request, полученный из битриксового\n- `bitrix.request.psr7` - Битриксовый Request, приведенный к PSR-7\n- `bitrix.response` - Symfony Response, полученный из битриксового\n- `bitrix.response.psr7` - Битриксовый Response, приведенный к PSR-7\n- `psr17.http_factory` - HttpFactory стандарта PSR-17\n- `psr18.http_client` - Http client стандарта PSR-18\n\n## Хэлперы\n\n1) `container()` - отдает экземпляр контейнера (выступает в роли сервис-локатора):\n\n```php\n$kernel = container()-\u003eget('kernel');\n```\n\n2) `delegatedContainer()` - отдает экземпляр манипулятора (реализующего интерфейс `Symfony\\Component\\DependencyInjection\\ContainerInterface`) \nделегированными контейнерами.\n\n```php\n$moduleService = delegatedContainer()-\u003eget('my_module_id.service');\n```\n\nВ контейнере делегированный контейнер помечается тэгом `delegated.container` (их может быть сколь угодно много):\n\n```yaml\n  module_notifier_container:\n    class: Symfony\\Component\\DependencyInjection\\ContainerInterface\n    factory: ['Proklung\\Notifier\\DI\\Services', 'getInstance']\n    tags:\n      - { name: 'delegated.container' }\n```\n\nДелегированный контейнер - автономный контейнер, сформированные в модуле, плагине и тому подобных местах.\n\n## Импорт в контейнер сервисов битриксового сервис-локатора\n\nАвтоматом подтягиваются в контейнер сервисы из битриксового сервис-локатора. [Формат](https://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=43\u0026LESSON_ID=14032),\nсекция `services` из `/bitrix/.settings.php` и `/bitrix/.settings_extra.php`. Также загрузчик пробегает\nпо списку установленных модулей и подцепляет их тоже.\n\nДля отдельных сервис-контейнеров (отнаследованных от `AbstractStandaloneServiceProvider`) такая загрузка\nне производится.\n\nЕсли эта фича не нужна, то нужно отнаследоваться от `ServiceProvider` и заглушить метод `loadBitrixServiceLocatorConfigs`.\n\n```php\nclass MyServiceProvider extends ServiceProvider\n{\n    /**\n     * {@inheritDoc}\n     */\n    protected function loadBitrixServiceLocatorConfigs(DelegatingLoader $loader) : void\n    {\n    }\n}\n```\n\n### BitrixSettingsDiAdapter\n\nАдаптер-импортер настроек битриксового сервис-локатора (`.settings.php`) в симфонический контейнер.\n\n- **`importParameters(ContainerInterface $container, array $settings, ?string $section = null)`** - импорт параметров.\n  `section` - если задано, то параметры лягут в именованную секцию параметров контейнера.  \n- **`importServices(ContainerInterface $container, array $services)`** - импорт сервисов. [Формат](https://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=43\u0026LESSON_ID=14032)\n\nСчитываются конфиги в Битриксе как-то так:\n\n```php\nuse Bitrix\\Main\\Config\\Configuration;\n\n$this-\u003econfig = Configuration::getInstance()-\u003eget('my_config') ?? [];\n// Из модуля\n$this-\u003eparameters = Configuration::getInstance('my.module')-\u003eget('parameters') ?? [];\n$this-\u003eservices = Configuration::getInstance('my.module')-\u003eget('services') ?? [];\n```\n\n### Совместимость с новым механизмом битриксовых роутов\n\nС версии `21.400.0` (от 16.07.2021) главного модуля в Битриксе появился [сносный](https://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=43\u0026CHAPTER_ID=013764\u0026LESSON_PATH=3913.3516.5062.13764) роутер.\n\nЧтобы использовать в этом контексте контейнер нужно:\n\n- В файле описания маршрутов (например, `/local/routes/web.php`) в самом верху подключить ядро. \n\nЭто важно, т.к. без этого сервис-провайдер завалится на стадии подключения файла с роутами; они подключаются раньше инициализации ядра.\nИ, если эту проблему еще можно решить, отключив проверку классов сервисов на существование, то запускающиеся автоматом сервисы по тэгу\n`service.bootstrap` обломятся стопроцентно.\n\n```php\nuse Local\\ExampleBitrixActionController;\nuse Prokl\\ServiceProvider\\ServiceProvider;\nuse Bitrix\\Main\\Routing\\Controllers\\PublicPageController;\nuse Bitrix\\Main\\Routing\\RoutingConfigurator;\n\nrequire_once($_SERVER[\"DOCUMENT_ROOT\"].\"/bitrix/modules/main/include/prolog_before.php\");\n\n$container = ServiceProvider::instance();\n\nreturn function (RoutingConfigurator $routes) use ($container) {\n\n    $routes-\u003eget('/countries3/{country}/', [$container-\u003eget(ExampleBitrixActionController::class), 'cacheAction'])\n            -\u003edefault('country', 'Russia')\n            -\u003ename('first_bitrix_route')\n    ;\n    \n    $routes-\u003eget('/', new PublicPageController('/index.php')); // Старый роут на статике.\n\n};\n```\n\nКласс битриксового контроллера (`ExampleBitrixActionController`) с заточкой под DI:\n\n```php\nnamespace Local;\n\nuse Bitrix\\Main\\Engine\\Contract\\RoutableAction;\nuse Bitrix\\Main\\Engine\\Controller;\nuse Symfony\\Component\\HttpKernel\\KernelInterface;\n\nclass ExampleBitrixActionController extends Controller implements RoutableAction\n{\n    /**\n     * @var KernelInterface $kernel\n     */\n    private $kernel;\n\n    public function __construct(KernelInterface $kernel)\n    {\n        $this-\u003ekernel = $kernel;\n        parent::__construct();\n    }\n\n    /**\n     * @return string|Controller\n     */\n    public static function getControllerClass() {\n        return ExampleBitrixActionController::class;\n    }\n\n    /**\n     * @return string\n     */\n    public static function getDefaultName() {\n        return 'testingAction';\n    }\n\n    public function cacheAction(string $country)\n    {\n        return ['cacheDir' =\u003e $this-\u003ekernel-\u003egetCacheDir(), 'country' =\u003e $country];\n    }\n\n    public function configureActions()\n    {\n        return [\n            'cache' =\u003e [\n                'prefilters' =\u003e [], 'postfilters' =\u003e [],\n            ],\n        ];\n    }\n}\n```\nОписывается сервисом так:\n\n```yaml\n  Local\\ExampleBitrixActionController:\n    arguments: ['@kernel']\n```\n\nНичего революционного, но так можно получить нормально-сконфигурированный класс контроллера, \nсо всякими зависимостями и т.п.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fproklung%2Fbitrix.core.symfony","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fproklung%2Fbitrix.core.symfony","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fproklung%2Fbitrix.core.symfony/lists"}