### Example component_epilog.php Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/framework/components.md This example shows how to use component_epilog.php to set the page title based on data from $arResult. ```php SetTitle($arResult['MY_TITLE']); ?> ``` -------------------------------- ### Define Web Routes Source: https://context7.com/bitrix-tools/framework-docs/llms.txt Define URL patterns and their corresponding controller actions using the `RoutingConfigurator`. This example sets up routes for a blog post resource with a prefix and named routes. ```php // /local/routes/web.php use Bitrix\Main\Routing\RoutingConfigurator; use My\Blog\Infrastructure\Controller\Post; return static function (RoutingConfigurator $routes) { $routes ->prefix('blog') ->name('blog.post.') ->where('code', '[\w\d\-]+') ->group(static function (RoutingConfigurator $routes) { $routes->get('', [Post::class, 'list'] )->name('list'); $routes->post('create/', [Post::class, 'add'] )->name('add'); $routes->get('{code}/', [Post::class, 'get'] )->name('get'); $routes->put('{code}/', [Post::class, 'update'])->name('update'); $routes->delete('{code}/',[Post::class, 'delete'])->name('delete'); }); }; ``` -------------------------------- ### Simple Filter Example Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/orm/querying-data.md Demonstrates a basic filter condition for querying user data. ```php \Bitrix\Main\UserTable::query() ->where([ ['ID', '>', 1], ['ACTIVE', true] ]) ->exec(); // WHERE `main_user`.`ID` > 1 AND `main_user`.`ACTIVE` = 'Y' ``` -------------------------------- ### Example HandlerSocket Configuration Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/database/handlersocket.md This configuration sets up both a standard MySQLi connection and a fast HandlerSocket connection for reading data. The 'default' connection uses MySQLi, while the 'handlersocket' connection is specifically for high-speed reads. ```php 'connections' => [ 'value' => [ // Основное соединение с MySQL базой данных через MySQLi 'default' => [ 'className' => \Bitrix\Main\DB\MysqliConnection::class, // Используем драйвер MySQLi для соединения 'host' => 'localhost:31006', // Хост базы данных с указанием порта (нестандартный порт 31006) 'database' => 'admin_bus', // Имя базы данных 'login' => 'admin_bus', // Имя пользователя для доступа к БД 'password' => 'admin_bus', // Пароль пользователя 'options' => 2, // Дополнительные опции соединения (2 - отложенное соединение) 'handlersocket' => [ 'read' => 'handlersocket', // Использование HandlerSocket для операций чтения ], ], // Настройки соединения HandlerSocket для чтения данных 'handlersocket' => [ 'className' => \Bitrix\Main\Data\HsphpReadConnection::class, // Специальный класс для работы с HandlerSocket 'host' => 'localhost', // Хост HandlerSocket 'port' => '9998', // Порт HandlerSocket ], ], 'readonly' => true, // Запрещает изменение настроек во время выполнения скрипта ], ``` -------------------------------- ### Nested Filter Example Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/orm/querying-data.md Shows how to create nested filter conditions for more complex queries. ```php use \Bitrix\Main\ORM\Query\Query; \Bitrix\Main\UserTable::query() ->where(Query::filter()->where([ ["ID", '>', 1], ['ACTIVE', true] ]))->exec(); // WHERE `main_user`.`ID` > 1 AND `main_user`.`ACTIVE` = 'Y' ``` -------------------------------- ### ISBN transformation example Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/orm/entity-operations.md Illustrates the transformation of ISBN values before and after data modification. ```text // до преобразования 978-0321127426 978-1-449-31428-6 9780201485677 // после преобразования 9780321127426 9781449314286 9780201485677 ``` -------------------------------- ### Example of working with ErrorCollection Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/framework/results-and-errors.md Demonstrates creating an ErrorCollection, adding multiple errors, retrieving a specific error by code, and iterating through all errors. Use error codes for identification and group errors in ErrorCollection. ```php use Bitrix\Main\ErrorCollection; use Bitrix\Main\Error; $errorCollection = new ErrorCollection(); // Добавляем ошибки $errorCollection->add([ new Error('Первая ошибка', 'ERROR_1'), new Error('Вторая ошибка', 'ERROR_2') ]); // Добавляем ошибку по одному $errorCollection->setError(new Error('Третья ошибка', 'ERROR_3')); // Получаем ошибку по коду $error = $errorCollection->getErrorByCode('ERROR_2'); if ($error) { echo 'Найдена ошибка: ' . $error->getMessage(); } // Перебираем ошибки foreach ($errorCollection as $error) { echo 'Код: ' . $error->getCode() . ', Сообщение: ' . $error->getMessage() . '
'; } ``` -------------------------------- ### Initialize and Manage Tagged Cache Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/performance/caching.md Initialize a cache, start data caching, register tags, and end the tag cache. This is useful for data that is rarely updated and requires instant cache invalidation upon changes. ```php use Bitrix\Main\Application; $cache = Application::getInstance()->getCache(); $cacheDir = 'my_cache_dir'; $taggedCache = Application::getInstance()->getTaggedCache(); // Проверяем наличие кеша if ($cache->initCache(3600, 'cache_key', $cacheDir)) { // Получаем данные из кеша $data = $cache->getVars(); } elseif ($cache->startDataCache()) { // Если кеша нет, получаем данные из базы $data = getDataFromDatabase(); // Помечаем кеш тегом $taggedCache->startTagCache($cacheDir); $taggedCache->registerTag('my_tag'); $taggedCache->endTagCache(); // Сохраняем результаты в кеш $cache->endDataCache($data); } ``` -------------------------------- ### Configure Monolog for MyService in .settings.php Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/advanced/logger.md Configures Monolog as the logger for MyService in the module's settings. This example shows how to instantiate a Monolog logger and push a StreamHandler to write logs to a file. ```php return [ 'services' => [ 'value' => [ \My\Testing\MyService::class => [ 'constructor' => static function() { $logger = new \Monolog\Logger('my-testing'); $logger->pushHandler( new \Monolog\Handler\StreamHandler('/var/log/php/my-testing.log') ); return new \My\Testing\MyService( $logger, ); }, ], ], 'readonly' => true, ], ]; ``` -------------------------------- ### Implement a Console Message Receiver Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/framework/messenger.md Extend AbstractReceiver to create a custom message handler for console mode. The worker must be manually started in CLI mode to process messages in a loop. ```php class SomeReceiver extends \Bitrix\Main\Messenger\Receiver\AbstractReceiver { protected function process(MessageInterface $message): void { echo "Message {$message->getId()} received\n"; } } // Для cli-режима нужно запускать воркер вручную: $worker = new \Bitrix\Main\Messenger\Internals\Worker(); $worker->process(); ``` -------------------------------- ### Create a String User Field Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/cms-basics/userfields.md Use CUserTypeEntity::Add to create a new user field. Specify ENTITY_ID, FIELD_NAME, USER_TYPE_ID, and other settings like labels and searchability. The field name must start with UF_. ```php $userTypeEntity = new CUserTypeEntity(); $userFields = [ 'ENTITY_ID' => 'IBLOCK_3_SECTION', 'FIELD_NAME' => 'UF_DEV2DAY_FIELD', 'USER_TYPE_ID' => 'string', 'XML_ID' => 'XML_ID_DEV2DAY_FIELD', 'SORT' => 500, 'MULTIPLE' => 'N', 'MANDATORY' => 'N', 'SHOW_FILTER' => 'N', 'SHOW_IN_LIST' => '', 'EDIT_IN_LIST' => '', 'IS_SEARCHABLE' => 'N', 'SETTINGS' => [ 'DEFAULT_VALUE' => '', 'SIZE' => '20', 'ROWS' => '1', 'MIN_LENGTH' => '0', 'MAX_LENGTH' => '0', 'REGEXP' => '', ], 'EDIT_FORM_LABEL' => [ 'ru' => 'Пользовательское свойство', 'en' => 'User field', ], 'LIST_COLUMN_LABEL' => [ 'ru' => 'Пользовательское свойство', 'en' => 'User field', ], 'LIST_FILTER_LABEL' => [ 'ru' => 'Пользовательское свойство', 'en' => 'User field', ], 'ERROR_MESSAGE' => [ 'ru' => 'Ошибка при заполнении пользовательского свойства', 'en' => 'An error in completing the user field', ], 'HELP_MESSAGE' => [ 'ru' => '', 'en' => '', ], ]; $userFieldId = $userTypeEntity->Add($userFields); ``` -------------------------------- ### Create Directory and Navigate Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/security/proactive-security.md Use this command to create a temporary directory for the antivirus and navigate into it. ```bash mkdir -p /tmp/kaspersky && cd /tmp/kaspersky ``` -------------------------------- ### Bitrix Framework CLI for Scaffolding and Management Source: https://context7.com/bitrix-tools/framework-docs/llms.txt Utilize `php bitrix.php` for scaffolding modules, controllers, events, requests, and running custom commands. Use `--help` for command-specific assistance. ```bash # Create a CRUD controller in module my.blog php bitrix.php make:controller post -m my.blog --actions=crud # → /local/modules/my.blog/lib/Infrastructure/Controller/Post.php ``` ```bash # Create a Web (read) and Ajax (write) controller split php bitrix.php make:controller post -m my.blog --actions=get,list -C Web php bitrix.php make:controller post -m my.blog --actions=add,update,delete -C Ajax ``` ```bash # Generate a typed event class php bitrix.php make:event TicketClosed -m my.helpdesk --no-interaction # → /local/modules/my.helpdesk/lib/Public/Event/TicketClosedEvent.php ``` ```bash # Generate an event handler php bitrix.php make:eventhandler TicketClosed \ --event-module my.helpdesk --handler-module my.helpdesk --no-interaction ``` ```bash # Generate a validated request DTO php bitrix.php make:request PostCreate -m my.blog --fields ``` ```bash # Get help for any command php bitrix.php make:controller --help ``` -------------------------------- ### Configure a FileLogger with Custom Settings in .settings.php Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/advanced/logger.md Sets up a FileLogger for 'main.HttpClient' in the global .settings.php file. This configuration includes specifying the log level and a custom formatter, demonstrating advanced logger customization. ```php return [ 'services' => [ 'value' => [ 'formatter.Arguments' => [ 'className' => '\\Bitrix\\Main\\Diag\\LogFormatter', 'constructorParams' => [true], ], ], 'readonly' => true, ], 'loggers' => [ 'value' => [ 'main.HttpClient' => [ 'constructor' => function (\Bitrix\Main\Web\HttpClient $http, $method, $url) { $http->setDebugLevel(\Bitrix\Main\Web\HttpDebug::ALL); return new \Bitrix\Main\Diag\FileLogger('/home/bitrix/www/log.txt'); }, 'level' => \Psr\Log\LogLevel::DEBUG, 'formatter' => 'formatter.Arguments', ], ], 'readonly' => true, ], ]; ``` -------------------------------- ### Configure HTTP Client Options Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/framework/settings.md Set default parameters for Bitrix\\Main\\Web\\HttpClient, such as timeouts, redirects, proxy settings, and SSL verification. Parameters marked with '*' are for backward compatibility only; PSR-18 mode is recommended for new projects. ```php 'http_client_options' => [ 'value' => [ // Таймауты 'waitResponse' => true, // Ожидать ответ на запрос (true) или вернуть управление сразу (false) 'socketTimeout' => 30, // Таймаут соединения с сервером в секундах 'streamTimeout' => 60, // Таймаут чтения данных в секундах // Работа с редиректами, только в режиме обратной совместимости 'redirect' => true, // * Разрешить автоматическое следование редиректам 'redirectMax' => 5, // * Максимальное количество редиректов 'version' => '1.0', // * Версия HTTP-протокола: '1.0' или '1.1' // Прокси-сервер 'proxyHost' => 'proxy.example.com', // Адрес прокси 'proxyPort' => 3128, // Порт прокси 'proxyUser' => 'user', // Логин для аутентификации 'proxyPassword' => 'password', // Пароль для аутентификации // SSL и безопасность 'disableSslVerification' => false, // Отключить проверку SSL-сертификатов (не используйте на боевом сайте) 'privateIp' => true, // Разрешить запросы к частным IP-адресам 'compress' => false, // Отправлять заголовок Accept-Encoding: gzip 'charset' => 'utf-8', // Кодировка для тела запроса 'bodyLengthMax' => 0, // Максимально допустимая длина тела запроса // Обработка ответов и событий 'responseBuilder' => null, // Кастомный построитель ответов, реализует Http\ResponseBuilderInterface 'sendEvents' => true, // Отправлять события // Отладка 'debugLevel' => \Bitrix\Main\Web\HttpDebug::NONE, // Уровень детализации отладки 'cookies' => [], // * Массив файлов cookie для отправки с запросом 'headers' => [], // * Массив HTTP-заголовков для отправки с запросом // Использование cURL 'useCurl' => false, // Использовать библиотеку cURL вместо внутренних потоков PHP 'curlLogFile' => '', // Путь к файлу для логов cURL, если useCurl = true ], 'readonly' => false, // Разрешить изменение настроек во время выполнения ], ``` -------------------------------- ### Basic Controller Structure and Actions Source: https://context7.com/bitrix-tools/framework-docs/llms.txt Define a controller by extending `BitrixMainEngineController`. Public methods suffixed with `Action` become accessible endpoints. Arguments are auto-wired by name and type from the request. Responses can be JSON, `HttpResponse`, files, or rendered components. ```php namespace My\Blog\Infrastructure\Controller; use Bitrix\Main\Engine\Controller; use Bitrix\Main\Engine\CurrentUser; use Bitrix\Main\UI\PageNavigation; use Bitrix\Main\Engine\JsonPayload; use Bitrix\Main\Error; use Bitrix\Main\Engine\Response\File; final class Post extends Controller { // Disable default CSRF + auth pre-filters for public read endpoints protected function getDefaultPreFilters(): array { return []; } // GET /blog/ — paginated list public function listAction(PageNavigation $nav, CurrentUser $user): array { return [ 'page' => $nav->getCurrentPage(), 'size' => $nav->getPageSize(), 'userId' => $user->getId(), ]; // {"status":"success","data":{"page":1,"size":20,"userId":5},"errors":[]} } // GET /blog/{code}/ — single post by URL param public function getAction(string $code): array { $post = \My\Blog\Post::getByCode($code); if (!$post) { $this->addError(new Error('Post not found', 'NOT_FOUND')); return null; } return ['code' => $code, 'title' => $post->getTitle()]; } // POST /blog/create/ — JSON body public function addAction(JsonPayload $json): array { $title = $json->getDataList()->get('title'); // ... save logic ... return ['created' => true, 'title' => $title]; } // Download a file public function exportAction(string $code): File { $path = $this->generateExportFile($code); return new File($path, "export-{$code}.csv", 'text/csv'); } // Render a view (requires main module >= 25.700.0) public function indexAction(): \Bitrix\Main\Engine\Response\Render\View { return $this->renderView('blog/index', ['posts' => \My\Blog\PostTable::getList()->fetchAll()]); // Loads template from /local/modules/my.blog/views/blog/index.php } } // Call via JavaScript: // BX.ajax.runAction('my:blog.Post.get', { data: { code: 'my-first-post' } }); // Direct HTTP: GET /bitrix/services/main/ajax.php?action=my:blog.Post.get&code=my-first-post ``` -------------------------------- ### Modify ISBN before adding Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/orm/entity-operations.md Use the `onBeforeAdd` event to clean and modify fields before they are saved. This example removes hyphens from an ISBN field. ```php class BookTable extends Entity.DataManager { ... public static function onBeforeAdd(Entity.Event $event) { $result = new Entity.EventResult; $data = $event->getParameter("fields"); if (isset($data['ISBN'])) { $cleanIsbn = str_replace('-', '', $data['ISBN']); // Удаляем дефисы из ISBN $result->modifyFields(['ISBN' => $cleanIsbn]); // Модифицируем поле ISBN } return $result; } } ``` -------------------------------- ### Configure Routing Settings Source: https://context7.com/bitrix-tools/framework-docs/llms.txt Register route configuration files in `/bitrix/.settings.php` to enable routing. This setting is read-only after initial configuration. ```php // /bitrix/.settings.php 'routing' => [ 'value' => ['config' => ['web.php']], 'readonly' => true, ], ``` -------------------------------- ### Add Values to a List Type Field Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/cms-basics/userfields.md Use CUserFieldEnum::SetEnumValues to add options to a list-type user field. The array key for each option must start with 'n'. ```php $enumField = new CUserFieldEnum(); $addEnum = []; $addEnum['n'.$i] = [ 'XML_ID' => $key, 'VALUE' => $value, 'DEF' => 'N', 'SORT' => $i*10 ]; $enumField->SetEnumValues($newID, $addEnum); ``` -------------------------------- ### Use RegExp Validator for ISBN Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/orm/orm-concepts.md Example of using a RegExp validator to ensure the ISBN field is at least 13 characters long and contains only digits and hyphens. The field is marked as required. ```php new Entity\StringField('ISBN', [ 'required' => true, // Поле обязательно для заполнения 'column_name' => 'ISBNCODE', // Имя столбца в базе данных 'validation' => function() { return [ new Entity\Validator\RegExp('/[\d-]{13,}/') // Валидатор для проверки формата ISBN ]; } ]) ``` -------------------------------- ### Create a Logger Instance Dynamically Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/advanced/logger.md Shows how to create a logger instance dynamically using the Logger::create method, passing a logger ID and additional parameters. ```php \Bitrix\Main\Diag\Logger::create('logger.id', [$this]); ``` -------------------------------- ### Create and Clean Cache Instance Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/performance/caching.md Instantiate a cache with support for old values and clean cache entries by key and directory. ```php // Создаем экземпляр кеша с поддержкой старых значений $cache = Bitrix\Main\Data\Cache::createInstance(['actual_data' => false]); // Удаляем кеш по ключу $cache->clean($key, $dir); ``` -------------------------------- ### Unmanaged, Managed, and Tagged Cache Implementation Source: https://context7.com/bitrix-tools/framework-docs/llms.txt Demonstrates how to use `\Bitrix\Main\Data\Cache` for TTL-based caching, managed cache for auto-invalidation on ORM writes, and tagged cache for tag-based invalidation. Configure cache backends in `.settings.php`. ```php use Bitrix\Main\Application; // --- Unmanaged cache (TTL-based) --- $cache = Application::getInstance()->getCache(); if ($cache->initCache(3600, 'catalog_popular_books', '/catalog/')) { $data = $cache->getVars(); } elseif ($cache->startDataCache()) { $data = BookTable::getList(['order' => ['READERS_COUNT' => 'DESC'], 'limit' => 10])->fetchAll(); if (empty($data)) { $cache->abortDataCache(); // don't cache empty results } else { $cache->endDataCache($data); } } ``` ```php // --- Managed cache (auto-invalidated on ORM changes) --- $mc = Application::getInstance()->getManagedCache(); if ($mc->read(3600, 'user_groups', 'b_group')) { $groups = $mc->get('user_groups_value'); } else { $groups = \Bitrix\Main\GroupTable::getList()->fetchAll(); $mc->set('user_groups_value', $groups); } ``` ```php // --- Tagged cache --- $tc = Application::getInstance()->getTaggedCache(); if ($cache->initCache(3600, 'book_42', '/books/')) { $book = $cache->getVars(); } elseif ($cache->startDataCache()) { $book = BookTable::getRowById(42); $tc->startTagCache('/books/'); $tc->registerTag('book_42'); $tc->endTagCache(); $cache->endDataCache($book); } // Invalidate: Application::getInstance()->getTaggedCache()->clearByTag('book_42'); ``` ```php // --- Redis configuration in /bitrix/.settings.php --- // 'cache' => ['value' => [ // 'type' => ['class_name' => '\Bitrix\Main\Data\CacheEngineRedis', 'extension' => 'redis'], // 'redis' => ['host' => '127.0.0.1', 'port' => '6379'], // 'sid' => $_SERVER['DOCUMENT_ROOT'] . '#01', // ]], ``` -------------------------------- ### Configure HandlerSocket Read Access Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/database/handlersocket.md Add this configuration to `/bitrix/.settings.php` under the 'default' key to enable HandlerSocket for read operations. Ensure a separate connection for HandlerSocket is defined with the correct host and port. ```php 'default' => [ 'className' => \Bitrix\Main\DB\MysqliConnection::class, 'handlersocket' => [ 'read' => 'handlersocket', // Использовать HandlerSocket для чтения ], ], ``` ```php 'handlersocket' => [ 'className' => \Bitrix\Main\Data\HsphpReadConnection::class, 'host' => 'localhost', // Хост сервера HandlerSocket 'port' => 9998, // Порт для чтения (обычно 9998) ], ``` -------------------------------- ### Loading Language File in component_epilog.php Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/framework/components.md Loads language phrases for `component_epilog.php` if they differ from the main component's phrases. Requires creating a `/lang/ru/component_epilog.php` file. ```php use \Bitrix\Main\Localization\Loc; Loc::loadLanguageFile(__FILE__); Loc::getMessage("MY_MESS"); ``` -------------------------------- ### Publish and Subscribe to Application Events Source: https://context7.com/bitrix-tools/framework-docs/llms.txt Create typed event classes and register handlers using `EventManager::registerEventHandler()`. Handlers return `EventResult` to signal success or cancel operations. Use `make:event` to generate event classes. ```php // Define event (generated by: php bitrix.php make:event TicketClosed -m my.helpdesk) namespace My\Helpdesk\Public\Event; use Bitrix\Main\Event; final class TicketClosedEvent extends Event { public function __construct( public readonly int $ticketId, public readonly ?string $closeReason, ) { parent::__construct('my.helpdesk', 'TicketClosed'); } } // Fire event (new TicketClosedEvent(ticketId: 123, closeReason: 'Resolved'))->send(); // Handler that can cancel the before-close flow use Bitrix\Main\EventResult; final class BeforeTicketCloseHandler { public static function handle(\My\Helpdesk\Public\Event\BeforeTicketCloseEvent $event): EventResult { if (self::hasOpenTasks($event->ticketId)) { return new EventResult( EventResult::ERROR, parameters: ['message' => 'Ticket still has open tasks'], moduleId: 'my.taskTracker', ); } return new EventResult(EventResult::SUCCESS); } } // Register once during module installation \Bitrix\Main\EventManager::getInstance()->registerEventHandler( fromModule: 'my.helpdesk', eventType: 'BeforeTicketClose', toModuleId: 'my.helpdesk', toClass: BeforeTicketCloseHandler::class, toMethod: 'handle', ); // Check results after send $event = new \My\Helpdesk\Public\Event\BeforeTicketCloseEvent(42, 'Done'); $event->send(); foreach ($event->getResults() as $r) { if ($r->getType() === EventResult::ERROR) { echo $r->getParameters()['message']; } } ``` -------------------------------- ### Register and Resolve Services with Service Locator (DI Container) Source: https://context7.com/bitrix-tools/framework-docs/llms.txt Register services in `.settings.php` or via API. The `ServiceLocator` implements PSR-11 and supports autowiring for automatic dependency resolution. Services can be registered lazily. ```php // /local/modules/my.blog/.settings.php return [ 'services' => [ 'value' => [ 'my.blog.postRepository' => [ 'className' => \My\Blog\Repository\PostRepository::class, ], 'my.blog.postService' => [ 'constructor' => static function () { $repo = \Bitrix\Main\DI\ServiceLocator::getInstance() ->get(\My\Blog\Repository\PostRepository::class); return new \My\Blog\Service\PostService($repo); }, ], \My\Blog\Contracts\PostRepositoryInterface::class => [ 'className' => \My\Blog\Repository\PostRepository::class, 'constructorParams' => static fn() => ['readonly' => true], ], ], 'readonly' => true, ], ]; // Resolve at runtime $locator = \Bitrix\Main\DI\ServiceLocator::getInstance(); $postService = $locator->get('my.blog.postService'); // Register lazily in code $locator->addInstanceLazy('my.blog.logger', [ 'className' => \My\Blog\Logger::class, ]); // Autowire: resolves even unregistered classes $service = $locator->get(\My\Blog\Service\PostService::class); ``` -------------------------------- ### Add Execute Permissions Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/security/proactive-security.md Grant execute permissions to the downloaded antivirus script. ```bash chmod +x kvrt.run ``` -------------------------------- ### Chained OR Logic Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/orm/querying-data.md Demonstrates creating OR conditions using a chain of where calls. ```php use \Bitrix\Main\ORM\Query\Query; \Bitrix\Main\UserTable::query() ->where('ACTIVE', true) ->where(Query::filter() ->logic('or') ->where('ID', 1) ->where('LOGIN', 'admin') ) ->exec(); // WHERE `main_user`.`ACTIVE` = 'Y' AND (`main_user`.`ID` = 1 OR `main_user`.`LOGIN` = 'admin') ``` -------------------------------- ### Configure FileLogger for MyService in .settings.php Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/advanced/logger.md Sets up a specific FileLogger for the MyService class within the module's configuration file. This ensures that log messages from MyService are written to a specified file. ```php return [ 'services' => [ 'value' => [ \My\Testing\MyService::class => [ 'constructor' => static function() { $logger = new \Bitrix\Main\Diag\FileLogger( '/var/log/php/my-testing.log', ); return new \My\Testing\MyService( $logger, ); }, ], ], 'readonly' => true, ], ]; ``` -------------------------------- ### Post Controller Actions Source: https://context7.com/bitrix-tools/framework-docs/llms.txt Demonstrates various actions within a Post controller, including listing posts, retrieving a single post, creating a new post, exporting data, and rendering views. ```APIDOC ## GET /blog/ — paginated list ### Description Retrieves a paginated list of blog posts. ### Method GET ### Endpoint /blog/ ### Parameters #### Query Parameters - **nav** (PageNavigation) - Required - Navigation object for pagination. - **user** (CurrentUser) - Required - Current user object. ### Response #### Success Response (200) - **page** (integer) - The current page number. - **size** (integer) - The number of items per page. - **userId** (integer) - The ID of the current user. ### Response Example ```json { "status": "success", "data": { "page": 1, "size": 20, "userId": 5 }, "errors": [] } ``` ``` ```APIDOC ## GET /blog/{code}/ — single post by URL param ### Description Retrieves a single blog post by its unique code. ### Method GET ### Endpoint /blog/{code}/ ### Parameters #### Path Parameters - **code** (string) - Required - The unique code of the post to retrieve. ### Response #### Success Response (200) - **code** (string) - The code of the post. - **title** (string) - The title of the post. #### Error Response (404) - **code** (string) - 'NOT_FOUND' - **message** (string) - 'Post not found' ### Response Example ```json { "status": "success", "data": { "code": "my-first-post", "title": "My First Post" }, "errors": [] } ``` ``` ```APIDOC ## POST /blog/create/ — JSON body ### Description Creates a new blog post using data provided in the JSON request body. ### Method POST ### Endpoint /blog/create/ ### Parameters #### Request Body - **title** (string) - Required - The title of the new post. ### Request Example ```json { "title": "New Post Title" } ``` ### Response #### Success Response (200) - **created** (boolean) - Indicates if the post was created successfully. - **title** (string) - The title of the created post. ### Response Example ```json { "status": "success", "data": { "created": true, "title": "New Post Title" }, "errors": [] } ``` ``` ```APIDOC ## Download a file ### Description Exports blog post data as a CSV file. ### Method GET (Implicit, based on context of returning a File object) ### Endpoint /blog/{code}/export/ ### Parameters #### Path Parameters - **code** (string) - Required - The code of the post to export. ### Response #### Success Response (200) - Returns a `File` response object containing the CSV data. ### Response Example (Returns a file download with Content-Type: text/csv) ``` ```APIDOC ## Render a view ### Description Renders a view for the blog index page, displaying a list of posts. ### Method GET (Implicit, based on context of rendering a view) ### Endpoint /blog/ ### Response #### Success Response (200) - Returns a `View` response object, typically rendering a PHP template. ### Response Example (Loads template from /local/modules/my.blog/views/blog/index.php) ``` -------------------------------- ### getList with ORM Filter Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/orm/querying-data.md Demonstrates using an ORM filter object with the getList method. ```php use \Bitrix\Main\ORM\Query\Query; \Bitrix\Main\UserTable::getList([ 'filter' => ['=ID' => 1] ]); \Bitrix\Main\UserTable::getList([ 'filter' => Query::filter() ->where('ID', 1) ]); // WHERE `main_user`.`ID` = 1 ``` -------------------------------- ### Download Kaspersky Virus Removal Tool Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/security/proactive-security.md Download the Kaspersky Virus Removal Tool executable using wget. ```bash wget https://devbuilds.s.kaspersky-labs.com/kvrt_linux/latest/kvrt.run ``` -------------------------------- ### ORM Querying with getList and Query Builder Source: https://context7.com/bitrix-tools/framework-docs/llms.txt Fetch data using getList with various parameters or the fluent query builder API. Supports filtering, sorting, limiting, and runtime fields. ```php use Bitrix\Main\ORM\Fields\ExpressionField; use Bitrix\Main\ORM\Query\Query; // --- getList with filter, order, limit, runtime field --- $result = BookTable::getList([ 'select' => ['ISBN', 'TITLE', 'PUBLISH_DATE', 'AGE_DAYS', 'CNT'], 'filter' => [ 'LOGIC' => 'OR', ['%=TITLE' => 'Patterns%'], ['=STATUS' => 'IN_STOCK'], ], 'order' => ['PUBLISH_DATE' => 'DESC'], 'limit' => 10, 'offset' => 0, 'runtime' => [new ExpressionField('CNT', 'COUNT(*)')], 'cache' => ['ttl' => 3600], ]); $rows = $result->fetchAll(); // --- Fluent query with OR condition and expression filter --- $books = BookTable::query() ->addSelect('TITLE') ->addSelect('AGE_DAYS') ->where('STATUS', 'IN_STOCK') ->where( Query::filter()->logic('or') ->where('TITLE', 'like', 'Pattern%') ->where('READERS_COUNT', '>', 100) ) ->whereNotNull('PUBLISH_DATE') ->setOrder(['AGE_DAYS' => 'DESC']) ->setLimit(5) ->fetchAll(); // --- Short helpers --- $row = BookTable::getRowById(42); // single row by PK $rows = BookTable::getRow([ 'filter' => ['=ISBN' => '9780321127426'], ]); // --- Count total without pagination --- $res = BookTable::getList(['count_total' => true]); $total = $res->getCount(); ``` -------------------------------- ### Run Kaspersky Virus Removal Tool Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/security/proactive-security.md Execute the antivirus tool with specified parameters. Ensure the -custom parameter points to your website's root directory. The report will be generated in /tmp/kaspersky/report/. ```bash ./kvrt.run --allowuser -- -accepteula -silent -dontencrypt -d "/tmp/kaspersky/report" -custom /home/bitrix/www/ ``` -------------------------------- ### Send a Message to a Queue Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/framework/messenger.md Create a message object and send it to a specified queue. Ensure the message data is serializable to JSON. ```php $message = new MyMessage(...); $message->send('first_queue'); ``` -------------------------------- ### Configure Routing Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/framework/settings.md Define which configuration files for routes to include from the specified directories. This allows for centralized management of application routing. ```php 'routing' => [ 'value' => [ 'config' => ['web.php'], // Можно добавить другие файлы: 'api.php', 'admin.php' ], 'readonly' => true, // Защищает настройки от изменений ], ``` -------------------------------- ### ExpressionField Usage Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/orm/querying-data.md Shows how to use ExpressionField for custom SQL conditions based on calculated values. ```php \Bitrix\Main\UserTable::query() ->where(new ExpressionField('LNG', 'LENGTH(%s)', 'LAST_NAME'), '>', 10) ->exec(); // WHERE LENGTH(`main_user`.`LAST_NAME`) > '10' ``` -------------------------------- ### Inject Logger into MyService via DI Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/advanced/logger.md Demonstrates injecting a LoggerInterface into a service class. If no logger is explicitly provided, a NullLogger is used by default, preventing any log output. ```php namespace My\Testing; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; final class MyService { public function __construct( private readonly LoggerInterface $logger = new NullLogger, ) {} public function test() { $this->logger->info('My message'); } } ``` -------------------------------- ### ReferenceField Basic Definition Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/orm/querying-data.md Illustrates the basic definition of a ReferenceField to establish a relationship between tables. ```php new Entity\ReferenceField('GROUP', GroupTable::class, Join::on('this.GROUP_ID', 'ref.ID') ) ``` -------------------------------- ### OR Logic Filter Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/orm/querying-data.md Illustrates how to combine conditions using OR logic within a filter. ```php use \Bitrix\Main\ORM\Query\Query; \Bitrix\Main\UserTable::query() ->where('ACTIVE', true) ->where(Query::filter() ->logic('or') ->where([ ['ID', 1], ['LOGIN', 'admin'] ]) )->exec(); // WHERE `main_user`.`ACTIVE` = 'Y' AND (`main_user`.`ID` = 1 OR `main_user`.`LOGIN` = 'admin') ``` -------------------------------- ### Basic Bitrix\Main\Result Usage Source: https://context7.com/bitrix-tools/framework-docs/llms.txt Use Result for standard return types in service operations, holding data and errors without exceptions for business logic failures. Check success with isSuccess() and retrieve errors. ```php use Bitrix\Main\Result; use Bitrix\Main\Error; use Bitrix\Main\ErrorCollection; use Bitrix\Main\Type\DateTime; // --- Basic Result --- function updateUserData(int $userId, array $fields): Result { $result = new Result(); if ($userId <= 0) { return $result->addError(new Error('Invalid user ID', 'INVALID_USER_ID')); } // ... database update ... $result->setData(['UPDATED_FIELDS' => $fields]); return $result; } $res = updateUserData(123, ['NAME' => 'Ivan']); if ($res->isSuccess()) { print_r($res->getData()['UPDATED_FIELDS']); } else { echo implode(', ', $res->getErrorMessages()); } // --- Typed Result subclass --- class UserUpdateResult extends Result { private array $updatedFields = []; private ?DateTime $timestamp = null; public function setUpdatedData(array $f, DateTime $t): void { $this->updatedFields = $f; $this->timestamp = $t; } public function getUpdatedFields(): array { return $this->updatedFields; } public function getTimestamp(): ?DateTime { return $this->timestamp; } } // --- ErrorCollection --- $coll = new ErrorCollection(); $coll->add([new Error('First error', 'ERR_1'), new Error('Second error', 'ERR_2')]); $err = $coll->getErrorByCode('ERR_2'); echo $err->getMessage(); // Second error ``` -------------------------------- ### Component Template Inclusion and Title Setting Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/framework/components.md Demonstrates the order of execution for including a component template and conditionally setting the page title based on component parameters. Operations after `IncludeComponentTemplate` will execute after `component_epilog.php` if they are in the main component code. ```php $this->IncludeComponentTemplate(); if($arParams["SET_TITLE"]) { $APPLICATION->SetTitle($arResult["NAME"]); } ``` -------------------------------- ### Serialize and unserialize data with callbacks Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/orm/entity-operations.md Configures a `TextField` to automatically serialize data before saving and unserialize it upon fetching using `save_data_modification` and `fetch_data_modification` callbacks. ```php new Entity.TextField('EDITIONS_ISBN', [ 'save_data_modification' => function () { return [ function ($value) { return serialize($value); // Преобразует значение в сериализованную строку перед сохранением } ]; }, 'fetch_data_modification' => function () { return [ function ($value) { return unserialize($value); // Преобразует сериализованную строку обратно в значение при извлечении } ]; } ]) ``` -------------------------------- ### Add USER_CONSENT Parameter to Component Settings Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/advanced/user-consent.md Declare the 'USER_CONSENT' parameter in the component's .parameters.php file to enable the User Consent section in the component settings. ```php [ ], 'PARAMETERS' => [ 'AJAX_MODE' => [], 'USER_CONSENT' => [], ], ]; ``` -------------------------------- ### Populating Template Data in template.php Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/framework/components.md Collects data within the component template file (`template.php`) to be potentially used in other parts of the component lifecycle. ```php count($arResult['ITEMS']), 'LAST_UPDATED' => $arResult['LAST_UPDATED'], ]; ?> ``` -------------------------------- ### Chained Column Reference in WHERE Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/orm/querying-data.md Shows how to reference columns through chained relationships within a WHERE clause. ```php ->whereColumn('this.AUTHOR.UserGroup:USER.GROUP.OWNER.ID', 'ref.ID'); ``` -------------------------------- ### Configure Blocking Mode in Memcache Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/performance/caching.md Enable blocking mode for Memcache by setting 'use_lock' to true in the cache configuration. ```php 'cache' => [ 'value' => [ 'type' => [ 'class_name' => '\Bitrix\Main\Data\CacheEngineMemcache', 'extension' => 'memcache', ], 'memcache' => ['host' => '127.0.0.1', 'port' => '11211'], 'use_lock' => true, // Включаем блокирующий режим 'sid' => 'bxMemcache', ], ], ``` -------------------------------- ### Send Message with Multiple Parameters Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/framework/messenger.md Send a message with both a delay and an item ID. This allows for deferred processing and specific message identification within the queue. ```php use Bitrix\Main\Messenger\Entity\ProcessingParam\DelayParam; use Bitrix\Main\Messenger\Entity\ProcessingParam\ItemIdParam; $message = new MyMessage(...); $message->send('first_queue', [new DelayParam(3600), new ItemIdParam('myid-123')]); ``` -------------------------------- ### Define a Custom Processing Parameter Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/framework/messenger.md Create a custom processing parameter by implementing ProcessingParamInterface. The applyTo method modifies the MessageBox before the message is sent to the broker. ```php interface ProcessingParamInterface { public function applyTo(MessageBox $messageBox): MessageBox; } ``` -------------------------------- ### Clear Cache by Tag Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/performance/caching.md Clear all cache entries within a specific directory by using the 'clearByTag' method with the tag name. ```php use Bitrix\Main\Application; Application::getInstance()->getTaggedCache()->clearByTag('my_tag'); ``` -------------------------------- ### Automatic data serialization with 'serialized' parameter Source: https://github.com/bitrix-tools/framework-docs/blob/main/pages/orm/entity-operations.md Enables automatic serialization and deserialization for a field by setting the `serialized` parameter to `true`. ```php new Entity.TextField('EDITIONS_ISBN', [ 'serialized' => true // Автоматически сериализует и десериализует данные ]) ```