diff --git a/pages/about/ecosystem.md b/pages/about/ecosystem.md index faa9b95..ecd283d 100644 --- a/pages/about/ecosystem.md +++ b/pages/about/ecosystem.md @@ -50,7 +50,7 @@ Bitrix Framework — PHP-платформа для разработки веб- Чтобы изучить связанные темы, перейдите к статьям: - [Архитектура](../framework/architecture.md), - [Жизненный цикл запроса](../framework/request-lifecycle.md), -- [Роутинг](../framework/routing.md). +- [Роутинг](../framework/routing.md). Если нужно сравнить платформу с другими решениями, используйте статьи: - [Отличия от других CMS](./cms-comparison.md), diff --git a/pages/advanced/datetime.md b/pages/advanced/datetime.md index d3ce198..04c9b6d 100644 --- a/pages/advanced/datetime.md +++ b/pages/advanced/datetime.md @@ -245,7 +245,7 @@ if (Date::isCorrect('31.02.2025', 'd.m.Y')) Конструктор создает объект даты со временем. ```php -new DateTime(?string $time = null, ?string $format = null, ?DateTimeZone $timezone = null) +new DateTime(?string $time = null, ?string $format = null, ?DateTimeZone $timezone = null) ``` - `$time` — строка с датой и временем. По умолчанию — текущее время. diff --git a/pages/advanced/debug.md b/pages/advanced/debug.md index 331fa62..c2a9d8d 100644 --- a/pages/advanced/debug.md +++ b/pages/advanced/debug.md @@ -188,10 +188,10 @@ foreach ($queries as $query) ```php use Bitrix\Main\Diag\Debug; - + // Запись в файл по умолчанию Debug::writeToFile($_SERVER, 'Данные сервера'); - + // Запись в указанный файл Debug::writeToFile($myArray, 'Мой массив', 'local/test_log.txt'); ``` @@ -225,7 +225,7 @@ foreach ($queries as $query) ```php use Bitrix\Main\Diag\Debug; - + // Запись структурированных данных в файл Debug::dumpToFile($_SESSION, 'Текущая сессия', 'local/logs/session_dump.log'); ``` diff --git a/pages/advanced/http-client.md b/pages/advanced/http-client.md index 6ffc3d1..0a11bc2 100644 --- a/pages/advanced/http-client.md +++ b/pages/advanced/http-client.md @@ -83,6 +83,7 @@ return [ ```php use Bitrix\Main\Config\Configuration; + print_r(Configuration::getValue('http_client_options')); ``` @@ -180,11 +181,11 @@ $url = "http://www.example.ru"; $url2 = "http://www.example.ru/form_request"; $post = "val1=true&val2=false"; -$httpClient = new HttpClient(); +$httpClient = new HttpClient(); $httpClient->query('GET', $url); $cookie = $httpClient->getCookies()->toArray(); -$httpClient->setHeader('Content-Type', 'application/x-www-form-urlencoded'); +$httpClient->setHeader('Content-Type', 'application/x-www-form-urlencoded'); $httpClient->setCookies($cookie); $response = $httpClient->post($url2, $post); ``` @@ -200,7 +201,7 @@ $response = $httpClient->post($url2, $post); ```php use Bitrix\Main\Web\HttpClient; use Bitrix\Main\Web\Http\Response; -use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\RequestInterface; $http = new HttpClient(); @@ -286,7 +287,7 @@ $request = new Request(Method::POST, $uri, [], $body); try { $response = $http->sendRequest($request); - + var_dump($response->getStatusCode()); var_dump($response->getHeaders()); var_dump((string)$response->getBody()); @@ -328,8 +329,8 @@ $data = [ 'k1' => 'v1', 'k2' => 'v2', 'k3' => [ - 'resource' => $res, // ссылка на открытый файл - 'filename' => 'pic.jpg', // имя файла, которое увидит сервер + 'resource' => $res, // ссылка на открытый файл + 'filename' => 'pic.jpg', // имя файла, которое увидит сервер ], ]; @@ -352,7 +353,7 @@ fclose($res); try { $response = $http->sendRequest($request); - + var_dump($response->getStatusCode()); var_dump($response->getHeaders()); var_dump((string)$response->getBody()); @@ -391,9 +392,9 @@ $request = new Request(Method::GET, $uri); try { do - { + { $response = $http->sendRequest($request); - + if ($response->hasHeader('Location')) { $location = $response->getHeader('Location')[0]; @@ -617,7 +618,7 @@ return [ 'loggers' => [ 'value' => [ 'main.HttpClient' => [ - 'constructor' => function (\Bitrix\Main\Web\Http\DebugInterface $debug, \Psr\Http\Message\RequestInterface $request) { + 'constructor' => function (\Bitrix\Main\Web\Http\DebugInterface $debug, \Psr\Http\Message\RequestInterface $request) { $debug->setDebugLevel(\Bitrix\Main\Web\HttpDebug::ALL); return new \Bitrix\Main\Diag\FileLogger('/home/bitrix/www/httplog'. spl_object_hash($request) . '.log'); }, @@ -643,7 +644,7 @@ return [ $logger = new \Bitrix\Main\Diag\FileLogger($_SERVER['DOCUMENT_ROOT'] . '/http.log'); $logger->setFormatter( - new class($request) implements \Bitrix\Main\Diag\LogFormatterInterface + new class($request) implements \Bitrix\Main\Diag\LogFormatterInterface { public function __construct(public \Psr\Http\Message\RequestInterface $request) {} diff --git a/pages/advanced/images.md b/pages/advanced/images.md index 5b8fe89..7554d94 100644 --- a/pages/advanced/images.md +++ b/pages/advanced/images.md @@ -222,7 +222,7 @@ if ($image->load()) { // Исходный прямоугольник по текущим размерам изображения $source = new Rectangle($image->getWidth(), $image->getHeight()); - + // Целевой прямоугольник с максимальными размерами $destination = new Rectangle(400, 400); @@ -303,10 +303,10 @@ $image = new Image('/home/bitrix/www/sticker.gif'); if ($image->load()) { - // ... после обработки + // ... после обработки $image->saveAs("/home/bitrix/www/resized_sticker.gif", 95, Image::FORMAT_GIF); // Освобождаем память - $image->clear(); + $image->clear(); } ``` diff --git a/pages/advanced/localization.md b/pages/advanced/localization.md index a389191..a3f5ef3 100644 --- a/pages/advanced/localization.md +++ b/pages/advanced/localization.md @@ -155,7 +155,9 @@ Loc::loadMessages($_SERVER['DOCUMENT_ROOT'] . '/local/myscript.php'); Метод `getMessage` возвращает сообщение по коду. ```php -\Bitrix\Main\Localization\Loc::getMessage($code, $replace, $language) +use Bitrix\Main\Localization\Loc; + +Loc::getMessage($code, $replace, $language) ``` - `$code` — код сообщения. Должен быть уникальным. @@ -167,7 +169,7 @@ Loc::loadMessages($_SERVER['DOCUMENT_ROOT'] . '/local/myscript.php'); В коде замените статичный текст на вызов метода `getMessage` с кодом языкового сообщения. ```php - + ``` **Пример.** Сообщение в языковом файле содержит шаблоны, вместо которых можно подставить данные. @@ -183,8 +185,7 @@ $MESS['WELCOME_TEXT'] = 'Привет, #NAME#! Количество новых В параметре `$replace` укажем, на что заменить шаблоны. ```php - 'Алексей', '#NUM#' => 5]); + 'Алексей', '#NUM#' => 5]); ?> ``` Результат — сообщение с текстом `Привет, Алексей! Количество новых сообщений: 5`. @@ -348,7 +349,7 @@ beforeCreate() { // Установить одну фразу this.$bitrix.Loc.setMessage('DEMO_COUNTER', 'Счетчик: #COUNTER#'); - + // Установить несколько фраз this.$bitrix.Loc.setMessage({ DEMO_COUNTER: 'Счетчик: #COUNTER#', diff --git a/pages/advanced/logger.md b/pages/advanced/logger.md index a439fe3..7592089 100644 --- a/pages/advanced/logger.md +++ b/pages/advanced/logger.md @@ -180,7 +180,7 @@ $logger->setFormatter($formatter); use Bitrix\Main\Diag\Helper; $logger->debug( - "{date} - {host}\n{trace}{delimiter}\n", + "{date} - {host}\n{trace}{delimiter}\n", [ 'trace' => Diag\Helper::getBackTrace(6, DEBUG_BACKTRACE_IGNORE_ARGS, 3) ] @@ -222,7 +222,7 @@ use Psr\Log; class MyClass implements Log\LoggerAwareInterface { use Log\LoggerAwareTrait; - + public function doSomething() { if ($this->logger) @@ -253,7 +253,7 @@ use Psr\Log; class MyClass implements Log\LoggerAwareInterface { use Log\LoggerAwareTrait; - + public function doSomething() { if ($logger = $this->getLogger()) @@ -376,7 +376,7 @@ return [ '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'); }, @@ -428,8 +428,8 @@ return [ 'value' => [ 'main.HttpClient' => [ 'constructor' => function (\Bitrix\Main\Web\Http\DebugInterface $debug, \Psr\Http\Message\RequestInterface $request) - { - // Включаем полную отладку HTTP-клиента + { + // Включаем полную отладку HTTP-клиента $debug->setDebugLevel(\Bitrix\Main\Web\HttpDebug::ALL); // Генерируем уникальное имя файла на основе хеша объекта запроса // Создаем отдельный файловый логгер для текущего запроса @@ -454,18 +454,18 @@ return [ 'main.HttpClient' => [ 'constructor' => function (\Bitrix\Main\Web\Http\DebugInterface $debug, \Psr\Http\Message\RequestInterface $request) { - // Включаем только логирование заголовков запроса + // Включаем только логирование заголовков запроса $debug->setDebugLevel(\Bitrix\Main\Web\HttpDebug::REQUEST_HEADERS); - + // Единый файл для всех внешних вызовов $logger = new \Bitrix\Main\Diag\FileLogger($_SERVER['DOCUMENT_ROOT'] . '/http.txt'); - + // Назначаем анонимный форматтер $logger->setFormatter( - new class($request) implements \Bitrix\Main\Diag\LogFormatterInterface + new class($request) implements \Bitrix\Main\Diag\LogFormatterInterface { public function __construct(public \Psr\Http\Message\RequestInterface $request) {} - + public function format($message, array $context = []): string { // Игнорируем запросы к push-серверу @@ -473,12 +473,12 @@ return [ { return ''; } - + return $this->request->getUri() . " \t" . $_SERVER['REQUEST_URI'] . "\n"; } } ); - + return $logger; }, 'level' => \Psr\Log\LogLevel::DEBUG, diff --git a/pages/advanced/multisite.md b/pages/advanced/multisite.md index 59f891d..a17beb3 100644 --- a/pages/advanced/multisite.md +++ b/pages/advanced/multisite.md @@ -301,18 +301,18 @@ Bitrix Framework поддерживает два режима многосайт Создание символических ссылок - ' . $strError . '
Путь: ' . htmlspecialchars($full_path); @@ -357,7 +357,7 @@ Bitrix Framework поддерживает два режима многосайт ?>
Путь к папке с ядром:
-

+

@@ -383,7 +383,7 @@ Bitrix Framework поддерживает два режима многосайт - `.access.php` — ограничивает доступ к публичной части сайта. Добавьте файл, если он есть на основном сайте. Файл содержит строку, которая разрешает всем пользователям просматривать корень сайта. ```php - + ``` #### Настроить виртуальные хосты diff --git a/pages/advanced/numerator.md b/pages/advanced/numerator.md index c617cb9..05883cc 100644 --- a/pages/advanced/numerator.md +++ b/pages/advanced/numerator.md @@ -48,7 +48,7 @@ $templateWords = Numerator::getTemplateWordsForType('DOCUMENT'); #| || **Генератор** | **Служебные слова** || || `RandomNumberGenerator` |`{RANDOM}` — случайная строка из заглавных латинских букв и цифр || -|| `DateNumberGenerator` |`{DAY}` — день месяца в момент генерации номера с ведущим нулем: `01`, `23` +|| `DateNumberGenerator` |`{DAY}` — день месяца в момент генерации номера с ведущим нулем: `01`, `23` `{MONTH}` — месяц в момент генерации номера с ведущим нулем: `03`, `11` `{YEAR}` — текущий год на момент генерации кода || || `SequentNumberGenerator` | `{NUMBER}` — уникальный последовательный номер || @@ -117,9 +117,9 @@ $settings = Numerator::getSettingsFields('DOCUMENT'); ['settingName' => 'year', 'value' => 'year', 'title' => 'В пределах года',],], ], ['settingName' => 'timezone', 'type' => 'array', 'values' => [...]], - ..., + // ..., ], - ..., + // ..., ], 'settingsWords' => [ 'Bitrix_Main_Numerator_Generator_SequentNumberGenerator' => ['{NUMBER}' => 'Последовательный номер',], @@ -346,7 +346,7 @@ $numerators = Numerator::getListByType('CRM_INVOICE'); ### Получить следующий номер ```php -$number = $numerator->getNext(); +$number = $numerator->getNext(); ``` ## Изменить настройки нумератора @@ -449,7 +449,7 @@ echo $numerator->getNext('A') . PHP_EOL; ```php use Bitrix\Main\Numerator\Numerator; - + Numerator::load($numeratorId, $hashable); ``` diff --git a/pages/advanced/stepper.md b/pages/advanced/stepper.md index cf8e8cf..894b895 100644 --- a/pages/advanced/stepper.md +++ b/pages/advanced/stepper.md @@ -19,7 +19,6 @@ description: 'Итератор. Продвинутые возможности Bi ```php processNextBatch($lastId, 50); - + // Сохраняем состояние для следующего запуска $option['last_processed_id'] = $processed['last_id']; $option['steps'] += $processed['count']; @@ -214,7 +213,7 @@ public function execute(array &$option) $option['processed_ids'], $processed['ids'] ); - + // Проверяем завершение return ($option['steps'] < $option['count']) ? self::CONTINUE_EXECUTION diff --git a/pages/advanced/user-consent.md b/pages/advanced/user-consent.md index eef9129..eaf8540 100644 --- a/pages/advanced/user-consent.md +++ b/pages/advanced/user-consent.md @@ -72,11 +72,7 @@ description: 'Пользовательские соглашения. Продв В файле параметров компонента `.parameters.php` объявите параметр `'USER_CONSENT' => []`. ```php - [ @@ -110,8 +106,8 @@ $arComponentParameters = [
- - IncludeComponent( + + IncludeComponent( 'bitrix:main.userconsent.request', '', [ @@ -125,7 +121,7 @@ $arComponentParameters = [ ], ] ); ?> - + ``` @@ -149,8 +145,8 @@ $arComponentParameters = [
- - IncludeComponent( + + IncludeComponent( 'bitrix:main.userconsent.request', '', [ @@ -165,7 +161,7 @@ $arComponentParameters = [ ], ] ); ?> - + ``` @@ -1086,11 +1117,11 @@ new BX.ExampleComponent({ ```javascript BX.ajax.runComponentAction(this.componentName, action, { - mode: 'class', - signedParameters: this.signedParameters, - data: data - }).then(function (response) { - // Обработка ответа + mode: 'class', + signedParameters: this.signedParameters, + data: data + }).then(function (response) { + // Обработка ответа }); ``` diff --git a/pages/framework/console-commands.md b/pages/framework/console-commands.md index f203433..6b7bf6a 100644 --- a/pages/framework/console-commands.md +++ b/pages/framework/console-commands.md @@ -69,10 +69,10 @@ Bitrix Framework включает готовые команды для разр ```bash # Создать компонент внутри модуля php bitrix.php make:component MyNamespace:MyComponent --module=my.module - + # Создать компонент в общей папке /bitrix/components/ php bitrix.php make:component MyNamespace:MyComponent --no-module - + # Создать компонент в папке /local/components/ php bitrix.php make:component MyNamespace:MyComponent --local -n ``` @@ -82,7 +82,7 @@ Bitrix Framework включает готовые команды для разр ```bash # Создать контроллер с CRUD-действиями php bitrix.php make:controller Post -m my.module --actions=crud -n - + # Создать контроллер с конкретными действиями php bitrix.php make:controller Post -m my.module --actions=list,get -n ``` @@ -221,7 +221,7 @@ php bitrix.php translate:index --path=/local/modules/my.module ```bash # Обновить все модули php bitrix.php update:modules - + # Обновить конкретные модули php bitrix.php update:modules -m main,iblock,ui ``` @@ -237,7 +237,7 @@ php bitrix.php translate:index --path=/local/modules/my.module ``` # Обновить все языковые пакеты php bitrix.php update:languages - + # Обновить конкретные языки php bitrix.php update:languages -l it,br,tr ``` diff --git a/pages/framework/controllers.md b/pages/framework/controllers.md index 8e910be..02f3a87 100644 --- a/pages/framework/controllers.md +++ b/pages/framework/controllers.md @@ -144,7 +144,7 @@ final class Post extends Controller ```php use Bitrix\Main\Routing\RoutingConfigurator; use My\Blog\Infrastructure\Controller\Post; - + return static function (RoutingConfigurator $routes) { $routes ->prefix('blog') @@ -376,7 +376,7 @@ GET /bitrix/services/main/ajax.php?action=my:blog.Post.get&code=my-first-blog ```php use Bitrix\Main\Routing\RoutingConfigurator; use My\Blog\Infrastructure\Controller\Web\Post; - + return static function (RoutingConfigurator $routes) { $routes ->prefix('blog') @@ -902,19 +902,19 @@ public function viewAction(string $code): \Bitrix\Main\Engine\Response\Component ```json { - "html": "HTML код компонента", - "assets": { - // списки используемых ресурсов - "js": [], - "css": [], - "strings": [], - }, - "additionalParams": { - // дополнительные параметры респонса, если указан аргумент $additionalResponseParams - }, - "componentResult": { - // результат работы компонента, если указан аргумент $dataKeys - } + "html": "HTML код компонента", + "assets": { + // списки используемых ресурсов + "js": [], + "css": [], + "strings": [], + }, + "additionalParams": { + // дополнительные параметры респонса, если указан аргумент $additionalResponseParams + }, + "componentResult": { + // результат работы компонента, если указан аргумент $dataKeys + } } ``` @@ -961,7 +961,8 @@ use Bitrix\Main\Error; public function deleteAction(string $code) { $blog = Blog::getByCode($code); - if (!$blog) { + if (!$blog) + { $this->addError(new Error('Блог не найден', 'BLOG_NOT_FOUND')); return null; } diff --git a/pages/framework/cookies.md b/pages/framework/cookies.md index 00a25d2..1bb668e 100644 --- a/pages/framework/cookies.md +++ b/pages/framework/cookies.md @@ -48,7 +48,7 @@ description: 'Cookie-файлы. Документация по Bitrix Framework: ```php use Bitrix\Main\Context; - + $request = Context::getCurrent()->getRequest(); ``` @@ -56,11 +56,14 @@ description: 'Cookie-файлы. Документация по Bitrix Framework: ```php $cookieValue = $request->getCookie("example_cookie"); - + // Проверка наличия и вывод значения - if ($cookieValue !== null) { + if ($cookieValue !== null) + { echo "Значение cookie: " . $cookieValue; - } else { + } + else + { echo "Cookie не найдено."; } ``` @@ -152,13 +155,15 @@ require $_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_before. use Bitrix\Main\Application; use Bitrix\Main\Web\Cookie; -if ($_SERVER['REQUEST_METHOD'] === 'POST' && $_POST['ACTION'] === 'selectMyCity') { +if ($_SERVER['REQUEST_METHOD'] === 'POST' && $_POST['ACTION'] === 'selectMyCity') +{ $APPLICATION->RestartBuffer(); header('Content-Type: application/json'); $response = ['STATUS' => 'ERROR', 'MESSAGE' => 'Не удалось добавить cookie']; - if (check_bitrix_sessid()) { + if (check_bitrix_sessid()) + { $city = $_POST['city']; $application = Application::getInstance(); @@ -204,9 +209,9 @@ function setCityCookie(city) { ## Шифрованные cookie -Шифрованные cookie `\Bitrix\Main\Web\CryptoCookie` позволяют передавать данные пользователю без раскрытия их содержимого и без изменения. +Шифрованные cookie `\Bitrix\Main\Web\CryptoCookie` позволяют передавать данные пользователю без раскрытия их содержимого и без изменения. -Для шифрования данных ядром необходимо указать `crypto_key` в файле настроек `/bitrix/.settings.php`. +Для шифрования данных ядром необходимо указать `crypto_key` в файле настроек `/bitrix/.settings.php`. {% note tip "" %} diff --git a/pages/framework/events.md b/pages/framework/events.md index d36618d..b2aad2a 100644 --- a/pages/framework/events.md +++ b/pages/framework/events.md @@ -79,7 +79,7 @@ use Bitrix\Main\Event; final class TicketClosedEvent extends Event { - public function __construct( + public function __construct( public readonly int $ticketId, public readonly ?string $closeReason, ) diff --git a/pages/framework/extensions.md b/pages/framework/extensions.md index be0b0aa..3d23897 100644 --- a/pages/framework/extensions.md +++ b/pages/framework/extensions.md @@ -81,13 +81,13 @@ description: 'Расширения. Документация по Bitrix Framewo ```javascript module.exports = { - input: './src/app.js', - output: './dist/app.bundle.js', + input: './src/app.js', + output: './dist/app.bundle.js', }; ``` В данном файле конфигурации не указываются файлы CSS. Их необходимо импортировать в файле, который указан в параметре `input` — точке входа сборки. - + ```javascript // Файл из input — src/app.js import './style.css'; // импорт CSS @@ -97,77 +97,77 @@ description: 'Расширения. Документация по Bitrix Framewo ```javascript module.exports = { - // Файл, для которого необходимо выполнить сборку. - // Необходимо указать относительный путь - input: string, - - // Путь к бандлу, который будет создан в результате сборки. - // Обычно это ./dist/.bundle.js - // Необходимо указать относительный путь - output: string || {js: string, css: string}, - - // Неймспейс, в который будут добавлены все экспорты из файла, - // указанного в input. Например, 'BX.Main.Filter' - namespace: string, - - // Списки файлов для принудительного объединения. - // Файлы будут объединены без проверок на дублирование кода. - // sourcemap's объединяются автоматически. - // Необходимо указать относительные пути - concat: { - js: Array, - css: Array, - }, - - // Разрешает или запрещает сборщику модифицировать config.php. - // По умолчанию true (разрешено) - adjustConfigPhp: boolean, - - // Разрешает или запрещает сборщику удалять неиспользуемый код. - // По умолчанию true (включено) - treeshake: boolean, - - // Разрешает или запрещает пересобирать бандлы, - // если сборка запущена не в корне текущего расширения. - // По умолчанию `false` (разрешено) - 'protected': boolean, - - plugins: { - // Переопределяет параметры Babel. - // Можно указать собственные параметры Babel - // https://babeljs.io/docs/en/options - // Если указать false, то код будет собран без транспиляции - babel: boolean | Object, - - // Дополнительные плагины Rollup, - // которые будут выполняться при сборке бандлов - custom: Array, - }, + // Файл, для которого необходимо выполнить сборку. + // Необходимо указать относительный путь + input: string, + + // Путь к бандлу, который будет создан в результате сборки. + // Обычно это ./dist/.bundle.js + // Необходимо указать относительный путь + output: string || {js: string, css: string}, + + // Неймспейс, в который будут добавлены все экспорты из файла, + // указанного в input. Например, 'BX.Main.Filter' + namespace: string, + + // Списки файлов для принудительного объединения. + // Файлы будут объединены без проверок на дублирование кода. + // sourcemap's объединяются автоматически. + // Необходимо указать относительные пути + concat: { + js: Array, + css: Array, + }, + + // Разрешает или запрещает сборщику модифицировать config.php. + // По умолчанию true (разрешено) + adjustConfigPhp: boolean, + + // Разрешает или запрещает сборщику удалять неиспользуемый код. + // По умолчанию true (включено) + treeshake: boolean, + + // Разрешает или запрещает пересобирать бандлы, + // если сборка запущена не в корне текущего расширения. + // По умолчанию `false` (разрешено) + 'protected': boolean, + + plugins: { + // Переопределяет параметры Babel. + // Можно указать собственные параметры Babel + // https://babeljs.io/docs/en/options + // Если указать false, то код будет собран без транспиляции + babel: boolean | Object, + + // Дополнительные плагины Rollup, + // которые будут выполняться при сборке бандлов + custom: Array, + }, // Определяет правила обработки путей к изображениям в CSS. // Доступно с версии 3.0.0 cssImages: { - // Определяет правило, по которому изображения должны + // Определяет правило, по которому изображения должны // быть обработаны: - // 'inline' — преобразует изображения в инлайн + // 'inline' — преобразует изображения в инлайн // 'copy' — копирует изображения в директорию 'output' // По умолчанию 'inline' - type: 'inline' | 'copy', - // Путь к директории, в которую должны быть скопированы - // используемые изображения + type: 'inline' | 'copy', + // Путь к директории, в которую должны быть скопированы + // используемые изображения output: string, - // Максимальный размер изображений в кб, которые могут быть + // Максимальный размер изображений в кб, которые могут быть // преобразованы в инлайн. // По умолчанию 14кб maxSize: number, - // Использовать ли svgo для оптимизации svg. - // По умолчанию true - svgo: boolean, + // Использовать ли svgo для оптимизации svg. + // По умолчанию true + svgo: boolean, }, resolveFilesImport: { - // Путь к директории, в которую должны быть скопированы - // импортированные изображения + // Путь к директории, в которую должны быть скопированы + // импортированные изображения output: string, - + // Определяет разрешенные для импорта типы файлов. // По умолчанию ['**/*.svg', '**/*.png', '**/*.jpg', '**/*.gif'] // https://github.com/isaacs/minimatch @@ -175,36 +175,36 @@ description: 'Расширения. Документация по Bitrix Framewo // По умолчанию [] exclude: Array, }, - - // Определяет правила Browserslist: + + // Определяет правила Browserslist: // false — не использовать (по умолчанию) // true — использовать файл .browserslist / .browserslistrc browserslist: boolean | string | Array, - - // Включает или отключает минификацию. - // По умолчанию отключено. + + // Включает или отключает минификацию. + // По умолчанию отключено. // Может принимать объект настроек Terser: // false — не минифицировать (по умолчанию) - // true — минифицировать с настройками по умолчанию - // object — минифицировать с указанными настройками + // true — минифицировать с настройками по умолчанию + // object — минифицировать с указанными настройками minification: boolean | object, - - // Включает или отключает преобразование нативных JS классов. - // По умолчанию значение параметра выставляется автоматически + + // Включает или отключает преобразование нативных JS классов. + // По умолчанию значение параметра выставляется автоматически // на основании browserslist transformClasses: boolean, - - // Включает или отключает создание Source Maps файлов + + // Включает или отключает создание Source Maps файлов sourceMaps: boolean, - - // Настройки тестов + + // Настройки тестов tests: { - // Настройки локализации + // Настройки локализации localization: { // Код языка локализации. По умолчанию 'en' languageId: string, - // Включает или выключает автозагрузку фраз в тестах. - // По умолчанию включено + // Включает или выключает автозагрузку фраз в тестах. + // По умолчанию включено autoLoad: boolean, }, }, @@ -220,66 +220,64 @@ description: 'Расширения. Документация по Bitrix Framewo - Базовая конфигурация. ```php - if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) - { - die(); - } + './dist/loader.bundle.css', - 'js' => './dist/loader.bundle.js', - 'rel' => [ - 'main.core' - ] + 'css' => './dist/loader.bundle.css', + 'js' => './dist/loader.bundle.js', + 'rel' => [ + 'main.core' + ] ]; - + ``` - Все параметры. ```php - ... + // ... return [ - // Путь к `css` файлу или массив путей - // Рекомендуем указывать относительный путь - 'css' => String | Array, - - // Путь к `js` файлу или массив путей к `js` файлам - // Рекомендуем указывать относительный путь - 'js' => String | Array, - - // Список зависимостей - // Необходимо указать имена расширений, которые должны быть - // подключены перед подключением текущего расширения - // Зависимости подключаются рекурсивно и с учетом указанного порядка - 'rel' => String | Array, - - // Путь к файлу с языковыми фразами или массив путей. - // Файл `lang//config.php` подключается автоматически, - // здесь его можно не указывать - 'lang' => String | Array, - - // Запрещает подключать `main.core` автоматически как зависимость. - // По умолчанию `false` — `main.core` подключается. - // При сборке бандла значение параметра устанавливается автоматически, - // если в коде нет прямой зависимости на `main.core` - 'skip_core' => Boolean, - - // Обработчик, который вызывается перед подключением расширения на странице. - // В качестве первого параметра будет передан массив конфигурации расширения. - // Обработчик может модифицировать этот массив и вернуть из функции. - // Это полезно, когда необходимо добавить в языковые фразы - // какие-то данные с сервера - 'oninit' => Function, - - // Дополнительные языковые фразы. - // Это полезно для передачи вычисляемых значений языковых фраз. - // Принимает массив. В качестве ключей необходимо указывать идентификаторы языковых фраз - 'lang_additional' => Array, - // Параметр доступен с версии 20.5.100 модуля main. - // Параметр позволяет указать настройки, - // которые могут быть получены в JS - // с помощью метода Extension.getSettings(). - 'settings' => Array + // Путь к `css` файлу или массив путей + // Рекомендуем указывать относительный путь + 'css' => String | Array, + + // Путь к `js` файлу или массив путей к `js` файлам + // Рекомендуем указывать относительный путь + 'js' => String | Array, + + // Список зависимостей + // Необходимо указать имена расширений, которые должны быть + // подключены перед подключением текущего расширения + // Зависимости подключаются рекурсивно и с учетом указанного порядка + 'rel' => String | Array, + + // Путь к файлу с языковыми фразами или массив путей. + // Файл `lang//config.php` подключается автоматически, + // здесь его можно не указывать + 'lang' => String | Array, + + // Запрещает подключать `main.core` автоматически как зависимость. + // По умолчанию `false` — `main.core` подключается. + // При сборке бандла значение параметра устанавливается автоматически, + // если в коде нет прямой зависимости на `main.core` + 'skip_core' => Boolean, + + // Обработчик, который вызывается перед подключением расширения на странице. + // В качестве первого параметра будет передан массив конфигурации расширения. + // Обработчик может модифицировать этот массив и вернуть из функции. + // Это полезно, когда необходимо добавить в языковые фразы + // какие-то данные с сервера + 'oninit' => Function, + + // Дополнительные языковые фразы. + // Это полезно для передачи вычисляемых значений языковых фраз. + // Принимает массив. В качестве ключей необходимо указывать идентификаторы языковых фраз + 'lang_additional' => Array, + // Параметр доступен с версии 20.5.100 модуля main. + // Параметр позволяет указать настройки, + // которые могут быть получены в JS + // с помощью метода Extension.getSettings(). + 'settings' => Array ]; ``` @@ -290,31 +288,31 @@ description: 'Расширения. Документация по Bitrix Framewo Пример описания расширения `main.loader`. ```javascript -declare module 'main.loader' +declare module 'main.loader' { - type loaderOptions = { - target?: HTMLElement, - size?: number, - mode?: 'absolute' | 'inline' | 'custom', - offset?: { - top?: string, - left?: string - }, - color?: string - }; - - class Loader - { - constructor(options?: loaderOptions); - readonly layout: HTMLElement; - readonly circle: HTMLElement; - createLayout(): HTMLElement; - show(target?: HTMLElement): Promise; - hide(): Promise; - isShown(): boolean; - setOptions(options: loaderOptions): void; - destroy(): void; - } + type loaderOptions = { + target?: HTMLElement, + size?: number, + mode?: 'absolute' | 'inline' | 'custom', + offset?: { + top?: string, + left?: string + }, + color?: string + }; + + class Loader + { + constructor(options?: loaderOptions); + readonly layout: HTMLElement; + readonly circle: HTMLElement; + createLayout(): HTMLElement; + show(target?: HTMLElement): Promise; + hide(): Promise; + isShown(): boolean; + setOptions(options: loaderOptions): void; + destroy(): void; + } } ``` @@ -324,33 +322,26 @@ declare module 'main.loader' Если структура `src` имеет вид: -- `src` - - - `entity` - - - `column.js` - - - `row.js` - - - `app.js` +``` +src/ +├── entity/ +│ ├── column.js +│ └── row.js +└── app.js +``` Директория `test` должна иметь следующую структуру: -- `test` - - - `entity` - - - `column` - - - `column.test.js` - - - `row` - - - `row.test.js` - - - `app` - - - `app.test.js` +``` +test/ +├── entity/ +│ ├── column/ +│ │ └── column.test.js +│ └── row/ +│ └── row.test.js +└── app/ + └── app.test.js +``` ## Использование расширений @@ -381,8 +372,8 @@ declare module 'main.loader' ```javascript import {Runtime} from 'main.core'; Runtime.loadExtension('main.loader').then((exports) => { - // Код, который использует `main.loader` - // В `exports` будут все экспорты из `main.loader` + // Код, который использует `main.loader` + // В `exports` будут все экспорты из `main.loader` }); ``` diff --git a/pages/framework/messenger.md b/pages/framework/messenger.md index 5194f40..ac307eb 100644 --- a/pages/framework/messenger.md +++ b/pages/framework/messenger.md @@ -53,23 +53,23 @@ use Bitrix\Main\Messenger\Entity\MessageInterface; class MyMessage extends AbstractMessage { - public function __construct( - public readonly string $text, // string — допустимый тип, сериализуется автоматически - public readonly int $superId // int — допустимый тип, сериализуется автоматически - ) {} - - public function jsonSerialize(): mixed // метод вернет массив простых типов - { - return [ - 'text' => $this->text, - 'superId' => $this->superId, - ]; - } - - public static function createFromData(array $data): MessageInterface - { - return new static(...$data); - } + public function __construct( + public readonly string $text, // string — допустимый тип, сериализуется автоматически + public readonly int $superId // int — допустимый тип, сериализуется автоматически + ) {} + + public function jsonSerialize(): mixed // метод вернет массив простых типов + { + return [ + 'text' => $this->text, + 'superId' => $this->superId, + ]; + } + + public static function createFromData(array $data): MessageInterface + { + return new static(...$data); + } } ``` @@ -83,13 +83,13 @@ use Bitrix\Main\Messenger\Receiver\AbstractReceiver; class MyReceiver extends AbstractReceiver { - /** - * @param MyMessage $message - */ - protected function process(MessageInterface $message): void - { - $this->superNotifier->send($message->text); - } + /** + * @param MyMessage $message + */ + protected function process(MessageInterface $message): void + { + $this->superNotifier->send($message->text); + } } ``` @@ -101,17 +101,17 @@ class MyReceiver extends AbstractReceiver [ - 'value' => [ - 'queues' => [ // список очередей - 'first_queue' => [ // очередь с именем 'first_queue' - 'handler' => \Bitrix\MyModule\Internals\Messenger\Receiver\MyReceiver::class, - ], - ], - ], - 'readonly' => true, // защита от перезаписи настроек через API - ], + ... // другие настройки, в том числе брокеров + 'messenger' => [ + 'value' => [ + 'queues' => [ // список очередей + 'first_queue' => [ // очередь с именем 'first_queue' + 'handler' => \Bitrix\MyModule\Internals\Messenger\Receiver\MyReceiver::class, + ], + ], + ], + 'readonly' => true, // защита от перезаписи настроек через API + ], ]; ``` @@ -148,35 +148,35 @@ $message->send('first_queue'); ```php return [ - 'messenger' => [ - 'value' => [ - 'run_mode' => 'web', // web, cli - 'brokers' => [ - 'default' => [ - 'type' => DbBroker::TYPE_CODE, // сейчас один тип — db - 'params' => [ - 'table' => MessengerMessageTable::class, - ] - ], - 'db_calendar' => [ - 'type' => 'db', - 'params' => [ - 'table' => 'b_calendar_messages', - 'module' => 'calendar', - ], - ], - ], - 'queues' => [ - 'first_queue' => [ - 'handler' => MyReceiver::class, - ], - 'google_section_sync' => [ - 'broker' => 'db_calendar', - 'handler' => GoogleSectionReceiver::class, - ], - ], - ], - 'readonly' => true, + 'messenger' => [ + 'value' => [ + 'run_mode' => 'web', // web, cli + 'brokers' => [ + 'default' => [ + 'type' => DbBroker::TYPE_CODE, // сейчас один тип — db + 'params' => [ + 'table' => MessengerMessageTable::class, + ] + ], + 'db_calendar' => [ + 'type' => 'db', + 'params' => [ + 'table' => 'b_calendar_messages', + 'module' => 'calendar', + ], + ], + ], + 'queues' => [ + 'first_queue' => [ + 'handler' => MyReceiver::class, + ], + 'google_section_sync' => [ + 'broker' => 'db_calendar', + 'handler' => GoogleSectionReceiver::class, + ], + ], + ], + 'readonly' => true, ]; ``` @@ -218,7 +218,7 @@ php bitrix.php messenger:consume ```php return [ - ... + ... 'messenger' => [ 'value' => [ 'queues' => [ @@ -311,7 +311,7 @@ return [ 'handler' => MyReceiver::class, 'retry_strategy' => [ 'max_retries' => 10, - 'delay' => 5, // базовая задержка — пять секунд + 'delay' => 5, // базовая задержка — пять секунд 'multiplier' => 2, // удваиваем с каждой попыткой 'max_delay' => 300 // максимум пять минут между попытками ], @@ -339,7 +339,7 @@ return [ ```php use Bitrix\Main\Messenger\Internals\Storage\Db\Model\MessengerMessageTable; - + class CalendarMessagesTable extends MessengerMessageTable { public static function getTableName(): string @@ -431,7 +431,8 @@ class SomeReceiver extends AbstractReceiver { protected function process(MessageInterface $message): void { - if ($message instanceof SectionMessage) { + if ($message instanceof SectionMessage) + { $section = $this->sectionRepository->getById($message->getSectionId()); (new SendSectionCommand($section))->run(); return; @@ -484,10 +485,10 @@ interface ReceiverInterface * @throws ReceiverException */ public function run(): void; - + // Установка лимита сообщений за одну итерацию public function setLimit(int $limit): self; - + // Назначение очереди public function setQueueId(string $queueId): self; @@ -588,7 +589,7 @@ interface ProcessingParamInterface ```php $message->setData([ 'task_id' => 123, - 'external_id' => 'trk-042' + 'external_id' => 'trk-042', ]); ``` diff --git a/pages/framework/pre-post-filters.md b/pages/framework/pre-post-filters.md index b4c9e0f..e813bf9 100644 --- a/pages/framework/pre-post-filters.md +++ b/pages/framework/pre-post-filters.md @@ -121,10 +121,10 @@ final class RedirectGuestToLogin extends Base public function onBeforeAction(Event $event) { $isAuthorized = $this->getAction()->getController()->getCurrentUser()?->getId() > 0; - if ($isAuthorized) - { - return; - } + if ($isAuthorized) + { + return; + } $requestUri = Application::getInstance() ->getContext() @@ -389,7 +389,7 @@ final class Entity extends \Bitrix\Main\Engine\Controller ], ]; } - + public function indexAction() { // ... @@ -438,14 +438,14 @@ final class Entity extends \Bitrix\Main\Engine\Controller new Authentication(), ]; } - + protected function getDefaultPostFilters() { return [ new Cors(), ]; } - + public function indexAction() { // ... @@ -488,7 +488,7 @@ final class Entity extends \Bitrix\Main\Engine\Controller new Csrf(), ]; } - + public function configureActions() { return [ @@ -503,7 +503,7 @@ final class Entity extends \Bitrix\Main\Engine\Controller ], ]; } - + public function indexAction() { // ... @@ -529,7 +529,7 @@ final class Entity extends \Bitrix\Main\Engine\Controller new Csrf(), ]; } - + #[EnablePrefilters([ new CloseSession(), ])] @@ -558,7 +558,7 @@ final class Entity extends \Bitrix\Main\Engine\Controller new Cors(), ]; } - + public function configureActions() { return [ @@ -573,12 +573,12 @@ final class Entity extends \Bitrix\Main\Engine\Controller ], ]; } - + public function indexAction() { // ... } - + #[EnablePostfilters([ new AnotherPostFilter(), ])] @@ -624,7 +624,7 @@ class CustomFilter extends \Bitrix\Main\Engine\ActionFilter\Base // Иначе результат обернут в стандартный JSON $customResponse = new \Bitrix\Main\HttpResponse(); - + $event->setParameter('result', $customResponse); } } diff --git a/pages/framework/request-response.md b/pages/framework/request-response.md index 3a4f039..f6b3a69 100644 --- a/pages/framework/request-response.md +++ b/pages/framework/request-response.md @@ -214,7 +214,7 @@ $response->setContent('Hello, world!'); // установить контент Content-Type: application/json; charset=UTF-8 "ping-pong" **/ - + new \Bitrix\Main\Engine\Response\Json([ 'id' => 2208, 'type' => 'license', @@ -249,7 +249,7 @@ $response->setContent('Hello, world!'); // установить контент "js": array, "string": array }, - "additionalParams": array + "additionalParams": array }, "errors": array } @@ -264,7 +264,8 @@ $response->setContent('Hello, world!'); // установить контент - [Zip/Archive](https://docs.1c-bitrix.ru/api/classes/Bitrix-Main-Engine-Response-Zip-Archive.html) — работает с архивом. Для NGINX можно использовать расширение mod_zip для создания архивов без нагрузки на PHP. ```php - use \Bitrix\Main\Engine\Response; + use Bitrix\Main\Engine\Response; + $archive = new Response\Zip\Archive('archive.zip'); $archive->addEntry(Response\Zip\ArchiveEntry::createFromFileId($fileId)); ``` @@ -281,7 +282,7 @@ $response->setContent('Hello, world!'); // установить контент ```php // сделать переадресацию с 302 статусом -$response = new \Bitrix\Main\Engine\Response\Redirect('/auth'); +$response = new \Bitrix\Main\Engine\Response\Redirect('/auth'); // сделать переадресацию с 301 статусом $response = new \Bitrix\Main\Engine\Response\Redirect('/auth'); @@ -320,7 +321,7 @@ $response->setStatus('301 Moved Permanently'); - `toJson()` — создает объект с форматом `OUTPUT_JSON_FORMAT`. ```php -use \Bitrix\Main\Engine\Response\Converter; +use Bitrix\Main\Engine\Response\Converter; // Преобразование строки: первая буква в нижний регистр + camelCase $converter = new Converter(Converter::LC_FIRST | Converter::TO_CAMEL); @@ -345,9 +346,9 @@ $result = $converter->process([ // Комбинация преобразований $converter = new Converter( - Converter::TO_SNAKE_DIGIT | - Converter::KEYS | - Converter::VALUES | + Converter::TO_SNAKE_DIGIT | + Converter::KEYS | + Converter::VALUES | Converter::RECURSIVE ); $result = $converter->process([ diff --git a/pages/framework/results-and-errors.md b/pages/framework/results-and-errors.md index b54edb9..3ecf69f 100644 --- a/pages/framework/results-and-errors.md +++ b/pages/framework/results-and-errors.md @@ -54,31 +54,38 @@ use Bitrix\Main\Error; function updateUserData(int $userId, array $fields): Result { $result = new Result(); - - if ($userId <= 0) { + + if ($userId <= 0) + { $result->addError(new Error('Неверный ID пользователя', 'INVALID_USER_ID')); return $result; } - + // Обновляем данные $updateResult = someUpdateFunction($userId, $fields); - - if ($updateResult === false) { + + if ($updateResult === false) + { $result->addError(new Error('Ошибка при обновлении данных', 'UPDATE_FAILED')); - } else { + } + else + { $result->setData(['UPDATED_FIELDS' => $fields]); } - + return $result; } // Используем функцию $result = updateUserData(123, ['NAME' => 'Иван', 'LAST_NAME' => 'Иванов']); -if ($result->isSuccess()) { +if ($result->isSuccess()) +{ $data = $result->getData(); echo 'Данные обновлены: ' . print_r($data, true); -} else { +} +else +{ $errors = $result->getErrorMessages(); echo 'Ошибки: ' . implode(', ', $errors); } @@ -122,18 +129,21 @@ function updateUserInDatabase(int $userId, array $fields): array function updateUserWithTypedResult(int $userId, array $fields): UserUpdateResult { $result = new UserUpdateResult(); - if ($userId <= 0) + if ($userId <= 0) { $result->addError(new Error('Invalid user ID', 100)); return $result; } - try { + try + { $updatedData = updateUserInDatabase($userId, $fields); $result->setUpdatedData( $updatedData, new DateTime() ); - } catch (Exception $e) { + } + catch (Exception $e) + { $result->addError(new Error($e->getMessage(), $e->getCode())); } return $result; @@ -141,12 +151,14 @@ function updateUserWithTypedResult(int $userId, array $fields): UserUpdateResult $typedResult = updateUserWithTypedResult(123, ['NAME' => 'Иван']); -if ($typedResult->isSuccess()) { +if ($typedResult->isSuccess()) +{ $fields = $typedResult->getUpdatedFields(); $time = $typedResult->getTimestamp()->format('Y-m-d H:i:s'); echo 'Данные обновлены. Поля: ' . print_r($fields, true) . ', Время: ' . $time; } -else { +else +{ echo 'Ошибки: ' . implode(', ', $typedResult->getErrorMessages()); } ``` @@ -184,12 +196,14 @@ $errorCollection->setError(new Error('Третья ошибка', 'ERROR_3')); // Получаем ошибку по коду $error = $errorCollection->getErrorByCode('ERROR_2'); -if ($error) { +if ($error) +{ echo 'Найдена ошибка: ' . $error->getMessage(); } // Перебираем ошибки -foreach ($errorCollection as $error) { +foreach ($errorCollection as $error) +{ echo 'Код: ' . $error->getCode() . ', Сообщение: ' . $error->getMessage() . '
'; } ``` diff --git a/pages/framework/routing.md b/pages/framework/routing.md index d7b843c..e287627 100644 --- a/pages/framework/routing.md +++ b/pages/framework/routing.md @@ -48,7 +48,7 @@ try_files $uri $uri/ /bitrix/routing_index.php; 'value' => [ 'config' => ['web.php'], // Можно добавить другие файлы: 'api.php', 'admin.php' ], - 'readonly' => true, // Защищает настройки от изменений + 'readonly' => true, // Защищает настройки от изменений ], ``` @@ -74,9 +74,7 @@ try_files $uri $uri/ /bitrix/routing_index.php; use Bitrix\Main\Routing\RoutingConfigurator; return static function (RoutingConfigurator $routes) { - $routes->any('/blog', static fn() => 'my blog'); // использует замыкание - }; ``` @@ -131,19 +129,19 @@ return static function (RoutingConfigurator $routes) { ]; } } - + class BlogIndexAction extends \Bitrix\Main\Engine\Action implements \Bitrix\Main\Engine\Contract\RoutableAction { public static function getControllerClass() { return BlogController::class; } - + public static function getDefaultName() { return 'view'; } - + public function run() { // ... @@ -191,7 +189,8 @@ $routes->options('/blog/post/{code}', [PostController::class, 'options']); ```php $routes ->any('/blog/post', [PostController::class, 'update']) - ->methods(['PUT', 'PATCH']); + ->methods(['PUT', 'PATCH']) +; ``` ## Параметры маршрута @@ -257,7 +256,8 @@ if ($app->hasCurrentRoute()) ```php $routes ->get('/blog/post/{code}', [PostController::class, 'view']) - ->where('code', '[\w\d\-]+'); + ->where('code', '[\w\d\-]+') +; ``` Теперь маршрут будет сопоставляться по регулярному выражению `/blog/post/(?[\w\d\-]+)`. @@ -269,7 +269,8 @@ $routes ```php $routes ->get('/blog/post/{code}/translate/{lang}', [PostController::class, 'translate']) - ->default('lang', 'en'); + ->default('lang', 'en') +; ``` - При переходе на `/blog/post/my-first-article/translate/` параметр `lang` получит значение `en`. @@ -283,7 +284,8 @@ $routes ->get('/blog/post/{code}', static function(string $code, string $lang) { // ... }) - ->default('lang', 'en'); + ->default('lang', 'en') + ; ``` ### Именованные маршруты @@ -295,7 +297,8 @@ $routes ```php $routes ->get('/blog/post/{code}', [PostController::class, 'view']) - ->name('blog.post.view'); + ->name('blog.post.view') +; ``` ### Группировка маршрутов @@ -474,7 +477,8 @@ $url = \Bitrix\Main\Application::getInstance()->getRouter()->route('blog.post.vi ```php $routes ->get('/blog/post-{code}/', [PostController::class, 'view']) - ->name('blog.post.view'); + ->name('blog.post.view') +; ``` Тот же код генерации будет создавать новый URL автоматически. @@ -515,7 +519,8 @@ array( $routes ->any('/blog/{SECTION_ID}/{ELEMENT_ID}/', new PublicPageController('/blog/detail.php')) ->where('SECTION_ID', '\d+') - ->where('ELEMENT_ID', '\d+'); + ->where('ELEMENT_ID', '\d+') +; ``` Контроллер `Bitrix\Main\Routing\Controllers\PublicPageController` подключит нужный физический файл. Но лучше перевести работу на контроллеры. @@ -524,7 +529,8 @@ $routes $routes ->any('/blog/{sectionId}/{elementId}/', [BlogController::class, 'detail']) ->where('sectionId', '\d+') - ->where('elementId', '\d+'); + ->where('elementId', '\d+') +; ``` ## Частые ошибки и решения diff --git a/pages/framework/service-locator.md b/pages/framework/service-locator.md index 64c4e93..80d4f66 100644 --- a/pages/framework/service-locator.md +++ b/pages/framework/service-locator.md @@ -12,7 +12,7 @@ Service Locator — это шаблон проектирования для уп ```php $serviceLocator = \Bitrix\Main\DI\ServiceLocator::getInstance(); if ($serviceLocator->has('someService')) -{ +{ $someService = $serviceLocator->get('someService'); } ``` diff --git a/pages/framework/sessions.md b/pages/framework/sessions.md index 9435cdd..98f0437 100644 --- a/pages/framework/sessions.md +++ b/pages/framework/sessions.md @@ -13,7 +13,7 @@ description: 'Сессии. Документация по Bitrix Framework: пр $session = \Bitrix\Main\Application::getInstance()->getSession(); if (!$session->has('foo')) { - $session->set('foo', 'bar'); + $session->set('foo', 'bar'); } echo $session['foo']; //bar ``` @@ -26,7 +26,8 @@ echo $session['foo']; //bar ```php $localStorage = \Bitrix\Main\Application::getInstance()->getLocalSession('someCategory'); -if (!isset($localStorage['productIds'])) { +if (!isset($localStorage['productIds'])) +{ $localStorage->set('productIds', [1, 2, 100]); $localStorage->set('price', 42); } @@ -95,7 +96,7 @@ define('BX_SECURITY_SESSION_VIRTUAL', true); ```php // bitrix/.settings.php return [ - //... + // ... 'session' => [ 'value' => [ 'mode' => 'default', @@ -114,6 +115,7 @@ return [ ```php // bitrix/.settings.php return [ + // ... 'session' => [ 'value' => [ 'mode' => 'default', @@ -136,7 +138,7 @@ return [ ```php // bitrix/.settings.php return [ - //... + // ... 'session' => [ 'value' => [ 'mode' => 'default', @@ -174,6 +176,7 @@ return [ ```php // bitrix/.settings.php return [ + // ... 'session' => [ 'value' => [ 'mode' => 'default', @@ -198,7 +201,7 @@ return [ ```php // bitrix/.settings.php return [ - //... + // ... 'session' => [ 'value' => [ 'mode' => 'default', @@ -219,7 +222,7 @@ return [ ```php // bitrix/.settings.php return [ - //... + // ... 'session' => [ 'value' => [ 'mode' => 'default', @@ -251,7 +254,7 @@ return [ ```php // bitrix/.settings.php return [ - //... + // ... 'session' => [ 'value' => [ 'mode' => 'default', @@ -272,7 +275,7 @@ return [ ```php // bitrix/.settings.php return [ -//... + // ... 'session' => [ 'value' => [ 'lifetime' => (int), @@ -280,10 +283,10 @@ return [ 'regenerateIdAfterLogin' => (bool), 'ignoreSessionStartErrors' => (bool), 'handlers' => [ - //... + // ... ], - ] - ] + ] + ] ]; ``` @@ -295,7 +298,7 @@ return [ - `ignoreSessionStartErrors` — если установлено `true`, фатальные ошибки при старте сессии будут игнорироваться. Например, ошибка подключения к серверу хранения сессий. При этом хит продолжит работать без сессии, а ошибки будут записываться только в лог. По умолчанию `false`. -## Разделенный режим сессии +## Разделенный режим сессии Чтобы включить разделенный режим сессии, внесите правки в конфигурационный файл `/bitrix/.settings.php`. @@ -307,11 +310,11 @@ return [ ```php return [ - //... + // ... 'session' => [ 'value' => [ 'mode' => 'separated', - 'lifetime' => 14400, + 'lifetime' => 14400, 'handlers' => [ 'kernel' => 'encrypted_cookies', 'general' => [ diff --git a/pages/framework/settings.md b/pages/framework/settings.md index b182908..ae885d6 100644 --- a/pages/framework/settings.md +++ b/pages/framework/settings.md @@ -313,14 +313,14 @@ description: 'Конфигурация ядра. Документация по B // Регистрация логгера для HTTP-клиента 'main.HttpClient' => [ 'className' => '\\Bitrix\\Main\\Diag\\FileLogger', // Класс логгера - 'constructorParams' => ['/home/bitrix/www/log.txt'], // Путь к файлу с параметрами конструктора + 'constructorParams' => ['/home/bitrix/www/log.txt'], // Путь к файлу с параметрами конструктора 'level' => \Psr\Log\LogLevel::DEBUG, // Уровень логирования: DEBUG, INFO, ERROR и так далее - 'formatter' => 'formatter.Arguments', // Опционально: ID форматтера из сервис-локатора + 'formatter' => 'formatter.Arguments', // Опционально: ID форматтера из сервис-локатора ], // Здесь можно добавить другие логгеры // 'my.component' => [ - ... - ], + // ... + // ], ], 'readonly' => true, // Защищает настройки от изменений во время выполнения ], @@ -337,7 +337,7 @@ description: 'Конфигурация ядра. Документация по B 'value' => [ 'config' => ['web.php'], // Можно добавить другие файлы: 'api.php', 'admin.php' ], - 'readonly' => true, // Защищает настройки от изменений + 'readonly' => true, // Защищает настройки от изменений ], ``` @@ -350,18 +350,18 @@ description: 'Конфигурация ядра. Документация по B Пример конфигурации для `memcache`: ```php - 'session' => [ - 'value' => [ - 'mode' => 'default', // Режим работы с сессиями - 'handlers' => [ - 'general' => [ - 'type' => 'memcache', // Тип хранилища - 'port' => '11211', // Порт сервера - 'host' => '127.0.0.1', // Хост сервера - ], +'session' => [ + 'value' => [ + 'mode' => 'default', // Режим работы с сессиями + 'handlers' => [ + 'general' => [ + 'type' => 'memcache', // Тип хранилища + 'port' => '11211', // Порт сервера + 'host' => '127.0.0.1', // Хост сервера ], - ] + ], ] +] ``` Подробнее в статье [Сессии](./sessions#%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B3%D1%83%D1%80%D0%B0%D1%86%D0%B8%D1%8F-%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85). @@ -371,12 +371,12 @@ description: 'Конфигурация ядра. Документация по B Секция `crypto` хранит ключ для шифрования конфиденциальных данных. Всегда используйте уникальный ключ. ```php - 'crypto' => [ - 'value' => [ - 'crypto_key' => 'mysupersecretphrase', // Рекомендуется использовать 32-символьную строку из a-z0-9 - ], - 'readonly' => true, - ] +'crypto' => [ + 'value' => [ + 'crypto_key' => 'mysupersecretphrase', // Рекомендуется использовать 32-символьную строку из a-z0-9 + ], + 'readonly' => true, +] ``` Подробнее в статье [Cookie-файлы](./cookies#%D1%88%D0%B8%D1%84%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5-cookie). diff --git a/pages/framework/storage.md b/pages/framework/storage.md index 75047e7..58cb68c 100644 --- a/pages/framework/storage.md +++ b/pages/framework/storage.md @@ -49,7 +49,8 @@ Bitrix Framework предлагает два решения для управл ```php $storage = \Bitrix\Main\DI\ServiceLocator::getInstance() - ->get(\Bitrix\Main\Data\Storage\PersistentStorageInterface::class); + ->get(\Bitrix\Main\Data\Storage\PersistentStorageInterface::class) +; ``` {% note tip "" %} @@ -70,7 +71,8 @@ $storage = \Bitrix\Main\DI\ServiceLocator::getInstance() ```php $storage = \Bitrix\Main\DI\ServiceLocator::getInstance() - ->get(\Bitrix\Main\Data\Storage\PersistentStorageInterface::class); + ->get(\Bitrix\Main\Data\Storage\PersistentStorageInterface::class) +; $storage->set('mymodule.feature_processing.feature123', ['somedata' => 12345], 3600); @@ -89,7 +91,8 @@ $storage->set('key', 'value', $interval); ```php $storage = \Bitrix\Main\DI\ServiceLocator::getInstance() - ->get(\Bitrix\Main\Data\Storage\PersistentStorageInterface::class); + ->get(\Bitrix\Main\Data\Storage\PersistentStorageInterface::class) +; $value = $storage->get('mymodule.feature_processing.feature123', 'default value'); @@ -172,7 +175,8 @@ $storage->deleteMultiple([ ```php // Получаем базовое хранилище $baseStorage = \Bitrix\Main\DI\ServiceLocator::getInstance() - ->get(\Bitrix\Main\Data\Storage\PersistentStorageInterface::class); + ->get(\Bitrix\Main\Data\Storage\PersistentStorageInterface::class) +; // Создаем декоратор с отложенным сохранением $deferredStorage = new \Bitrix\Main\Data\Storage\DeferredStorageDecorator($baseStorage); @@ -195,7 +199,8 @@ $deferredStorage->save(); ```php $baseStorage = \Bitrix\Main\DI\ServiceLocator::getInstance() - ->get(\Bitrix\Main\Data\Storage\PersistentStorageInterface::class); + ->get(\Bitrix\Main\Data\Storage\PersistentStorageInterface::class) +; $deferredStorage = new \Bitrix\Main\Data\Storage\DeferredStorageDecorator($baseStorage); ``` diff --git a/pages/framework/validation.md b/pages/framework/validation.md index 86b6564..d29af9a 100644 --- a/pages/framework/validation.md +++ b/pages/framework/validation.md @@ -38,7 +38,7 @@ public function __construct(int $userId) private ?int $id; private ?string $email; private ?string $phone; - + // getters & setters ... } ``` @@ -50,19 +50,19 @@ public function __construct(int $userId) use Bitrix\Main\Validation\Rule\Email; use Bitrix\Main\Validation\Rule\Phone; use Bitrix\Main\Validation\Rule\PositiveNumber; - + #[AtLeastOnePropertyNotEmpty(['email', 'phone'])] final class User { #[PositiveNumber] private ?int $id; - + #[Email] private ?string $email; - + #[Phone] private ?string $phone; - + // getters & setters... } ``` @@ -75,28 +75,28 @@ public function __construct(int $userId) use Bitrix\Main\DI\ServiceLocator; use Bitrix\Main\Result; use Bitrix\Main\Validation\ValidationService; - + class UserService { private ValidationService $validation; - + public function __construct() { $this->validation = ServiceLocator::getInstance()->get('main.validation.service'); } - + public function create(?string $email, ?string $phone): Result { $user = new User(); $user->setEmail($email); $user->setPhone($phone); - + $result = $this->validation->validate($user); if (!$result->isSuccess()) { return $result; } - + // save logic ... } } @@ -125,6 +125,7 @@ class Buyer #[Validatable] public ?Order $order; } + class Order { #[PositiveNumber] @@ -132,6 +133,7 @@ class Order #[Validatable] public ?Payment $payment; } + class Payment { #[NotEmpty] @@ -139,6 +141,7 @@ class Payment #[NotEmpty(errorMessage: 'Custom message error')] public string $systemCode; } + // validation /** @var \Bitrix\Main\Validation\ValidationService $validationService */ $validationService = \Bitrix\Main\DI\ServiceLocator::getInstance()->get('main.validation.service'); @@ -151,6 +154,7 @@ foreach ($result1->getErrors() as $error) echo $error->getCode() . ': ' . $error->getMessage(). PHP_EOL; } echo PHP_EOL; + $buyer->id = 1; $order = new Order(); $order->id = -1; @@ -162,6 +166,7 @@ foreach ($result2->getErrors() as $error) echo $error->getCode() . ': ' . $error->getMessage(). PHP_EOL; } echo PHP_EOL; + $buyer->order->id = 123; $payment = new Payment(); $payment->status = ''; @@ -201,9 +206,8 @@ final class UserSettingsDto // Все элементы массива должны быть целыми числами #[ElementsType(Type::Integer)] // Используем элемент перечисления public array $favoriteIds = [] - ) - { - } + ) + {} } // Пример использования @@ -235,8 +239,7 @@ final class TagDto #[Length(max: 20)] public string $name ) - { - } + {} } final class ArticleDto @@ -246,8 +249,7 @@ final class ArticleDto #[ElementsType(TagDto::class)] public array $tags = [] ) - { - } + {} } // Использование @@ -259,8 +261,10 @@ $article->tags = [ ]; $result = $validationService->validate($article); -if (!$result->isSuccess()) { - foreach ($result->getErrors() as $error) { +if (!$result->isSuccess()) +{ + foreach ($result->getErrors() as $error) + { // Путь к ошибке будет включать индекс элемента, например: "tags.2.name" echo $error->getCode() . ': ' . $error->getMessage() . PHP_EOL; } @@ -286,15 +290,14 @@ final class CreateUserDto public function __construct( #[PhoneOrEmail] public ?string $login, - + #[NotEmpty] public ?string $password, - + #[NotEmpty] public ?string $passwordRepeat, ) - { - } + {} } ``` @@ -309,29 +312,29 @@ use Bitrix\Main\Validation\ValidationService; class UserController extends Controller { private ValidationService $validation; - + protected function init() { parent::init(); - + $this->validation = ServiceLocator::getInstance()->get('main.validation.service'); } - + public function createAction(): Result { $dto = new CreateUserDto(); $dto->login = (string)$this->getRequest()->get('login'); $dto->password = (string)$this->getRequest()->get('password'); $dto->passwordRepeat = (string)$this->getRequest()->get('passwordRepeat'); - + $result = $this->validation->validate($dto); if (!$result->isSuccess()) { $this->addErrors($result->getErrors()); - + return false; } - + // create logic ... } } @@ -349,15 +352,15 @@ final class CreateUserDto public function __construct( #[PhoneOrEmail] public ?string $login = null, - + #[NotEmpty] public ?string $password = null, - + #[NotEmpty] public ?string $passwordRepeat = null, ) {} - + public static function createFromRequest(\Bitrix\Main\HttpRequest $request): self { return new static( @@ -386,7 +389,7 @@ class UserController extends Controller ), ]; } - + public function createAction(CreateUserDto $dto): Result { // create logic ... @@ -439,8 +442,7 @@ class User #[PositiveNumber(errorMessage: 'Invalid ID!')] public readonly int $id ) - { - } + {} } $user = new User(-150); /** @var \Bitrix\Main\Validation\ValidationService $service */ @@ -462,8 +464,7 @@ class User #[PositiveNumber] public readonly int $id ) - { - } + {} } $user = new User(-150); /** @var \Bitrix\Main\Validation\ValidationService $service */ @@ -581,8 +582,8 @@ final class Min implements ValidatorInterface public function __construct( private readonly int $min ) - { - } + {} + public function validate(mixed $value): ValidationResult { $result = new ValidationResult(); @@ -660,8 +661,7 @@ final class Range extends AbstractPropertyValidationAttribute private readonly int $max, protected ?string $errorMessage = null ) - { - } + {} protected function getValidators(): array { @@ -692,7 +692,7 @@ class NotOne extends AbstractClassValidationAttribute { $result = new ValidationResult(); $properties = (new ReflectionClass($object))->getProperties(); - + if (count($properties) > 2) { $result->addError(new ValidationError('Класс содержит слишком много свойств')); diff --git a/pages/get-started/create-component.md b/pages/get-started/create-component.md index 12cc422..910e933 100644 --- a/pages/get-started/create-component.md +++ b/pages/get-started/create-component.md @@ -31,10 +31,10 @@ description: 'Создание компонента. Пошаговое руко ├── .parameters.php // Параметры компонента ├── class.php // Логика компонента ├── templates/ -│ ├── .default/ -│ │ ├── template.php // Шаблон вывода -│ │ ├── script.js // Логика для карточки -│ │ └── style.css // Стили карточки +│ └── .default/ +│ ├── template.php // Шаблон вывода +│ ├── script.js // Логика для карточки +│ └── style.css // Стили карточки └── lang/ └── ru/ └── messages.php // Локализация @@ -178,6 +178,7 @@ class UserCardComponent extends CBitrixComponent ->where('ID', $userId) ->fetch() ; + if (empty($user)) { return; @@ -213,11 +214,10 @@ class UserCardComponent extends CBitrixComponent ```php " alt="" > - + - +

@@ -344,19 +344,16 @@ $MESS['USER_CARD_EMAIL_LABEL'] = 'E-mail:'; ```php SetTitle(''); -?> -IncludeComponent( "my:user.card", "", - Array( + [ "SHOW_EMAIL" => "Y", "USER_ID" => "1" /* или "USER_ID" => $USER->GetID() для текущего пользователя */ - ) + ] ); require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/footer.php'); diff --git a/pages/get-started/create-controller.md b/pages/get-started/create-controller.md index 818eda3..2fd12d2 100644 --- a/pages/get-started/create-controller.md +++ b/pages/get-started/create-controller.md @@ -133,7 +133,6 @@ BX.ajax.runAction('my:module.user.like', { /* данные */ }); ```php
@@ -328,12 +325,12 @@ $additionalUserCardContainers = $arResult['HAS_LIKE'] ? 'my-user-card__like-text >
- +

- +
IsAuthorized()): ?>