diff --git a/pages/advanced/http-client.md b/pages/advanced/http-client.md index 6ffc3d1..f18f9d1 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')); ``` @@ -328,8 +329,8 @@ $data = [ 'k1' => 'v1', 'k2' => 'v2', 'k3' => [ - 'resource' => $res, // ссылка на открытый файл - 'filename' => 'pic.jpg', // имя файла, которое увидит сервер + 'resource' => $res, // ссылка на открытый файл + 'filename' => 'pic.jpg', // имя файла, которое увидит сервер ], ]; @@ -391,7 +392,7 @@ $request = new Request(Method::GET, $uri); try { do - { + { $response = $http->sendRequest($request); if ($response->hasHeader('Location')) @@ -399,8 +400,7 @@ try $location = $response->getHeader('Location')[0]; $request = $request->withUri(new Uri($location)); } - } - while ($response->hasHeader('Location')); + } while ($response->hasHeader('Location')); } catch (ClientException $e) { diff --git a/pages/advanced/localization.md b/pages/advanced/localization.md index a389191..f4e484b 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`. diff --git a/pages/advanced/multisite.md b/pages/advanced/multisite.md index 59f891d..36d7b9f 100644 --- a/pages/advanced/multisite.md +++ b/pages/advanced/multisite.md @@ -301,7 +301,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..1a951fc 100644 --- a/pages/advanced/numerator.md +++ b/pages/advanced/numerator.md @@ -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}' => 'Последовательный номер',], diff --git a/pages/advanced/user-consent.md b/pages/advanced/user-consent.md index eef9129..0f76ce5 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/controllers.md b/pages/framework/controllers.md index 8e910be..01f9986 100644 --- a/pages/framework/controllers.md +++ b/pages/framework/controllers.md @@ -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..b2bb0ef 100644 --- a/pages/framework/cookies.md +++ b/pages/framework/cookies.md @@ -58,9 +58,12 @@ description: 'Cookie-файлы. Документация по Bitrix Framework: $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(); diff --git a/pages/framework/extensions.md b/pages/framework/extensions.md index be0b0aa..f24730e 100644 --- a/pages/framework/extensions.md +++ b/pages/framework/extensions.md @@ -81,8 +81,8 @@ description: 'Расширения. Документация по Bitrix Framewo ```javascript module.exports = { - input: './src/app.js', - output: './dist/app.bundle.js', + input: './src/app.js', + output: './dist/app.bundle.js', }; ``` @@ -97,52 +97,52 @@ 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: { @@ -220,16 +220,14 @@ 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' + ] ]; ``` @@ -237,49 +235,49 @@ description: 'Расширения. Документация по Bitrix Framewo - Все параметры. ```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 ]; ``` @@ -292,29 +290,29 @@ description: 'Расширения. Документация по Bitrix Framewo ```javascript declare module 'main.loader' { - type loaderOptions = { - target?: HTMLElement, - size?: number, - mode?: 'absolute' | 'inline' | 'custom', - offset?: { - top?: string, - left?: string - }, - color?: string - }; + 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; - } + 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..ee5368a 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' => [ @@ -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; @@ -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..76db3cc 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() diff --git a/pages/framework/request-response.md b/pages/framework/request-response.md index 3a4f039..9f3fb1d 100644 --- a/pages/framework/request-response.md +++ b/pages/framework/request-response.md @@ -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)); ``` @@ -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); diff --git a/pages/framework/results-and-errors.md b/pages/framework/results-and-errors.md index b54edb9..56693e4 100644 --- a/pages/framework/results-and-errors.md +++ b/pages/framework/results-and-errors.md @@ -55,7 +55,8 @@ 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; } @@ -63,9 +64,12 @@ function updateUserData(int $userId, array $fields): Result // Обновляем данные $updateResult = someUpdateFunction($userId, $fields); - if ($updateResult === false) { + if ($updateResult === false) + { $result->addError(new Error('Ошибка при обновлении данных', 'UPDATE_FAILED')); - } else { + } + else + { $result->setData(['UPDATED_FIELDS' => $fields]); } @@ -75,10 +79,13 @@ function updateUserData(int $userId, array $fields): 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..3b4e336 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'); // использует замыкание - }; ``` @@ -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..ebe2211 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,7 +283,7 @@ return [ 'regenerateIdAfterLogin' => (bool), 'ignoreSessionStartErrors' => (bool), 'handlers' => [ - //... + // ... ], ] ] @@ -307,7 +310,7 @@ return [ ```php return [ - //... + // ... 'session' => [ 'value' => [ 'mode' => 'separated', diff --git a/pages/framework/settings.md b/pages/framework/settings.md index b182908..2917612 100644 --- a/pages/framework/settings.md +++ b/pages/framework/settings.md @@ -315,12 +315,12 @@ description: 'Конфигурация ядра. Документация по B 'className' => '\\Bitrix\\Main\\Diag\\FileLogger', // Класс логгера '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..2e07651 100644 --- a/pages/framework/validation.md +++ b/pages/framework/validation.md @@ -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 = ''; @@ -202,8 +207,7 @@ 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; } @@ -293,8 +297,7 @@ final class CreateUserDto #[NotEmpty] public ?string $passwordRepeat, ) - { - } + {} } ``` @@ -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 { diff --git a/pages/get-started/create-component.md b/pages/get-started/create-component.md index 12cc422..d20cdf8 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 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..c7115a5 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
@@ -468,15 +465,11 @@ BX.ready(() => { ```php where('ID', $userId) ->fetch() - ; + ; + if (empty($user)) { return; diff --git a/pages/get-started/install-distr.md b/pages/get-started/install-distr.md index 6a66da0..d7977c7 100644 --- a/pages/get-started/install-distr.md +++ b/pages/get-started/install-distr.md @@ -224,7 +224,7 @@ return array ( 'readonly' => false, ), // настройки обработки ошибок - 'exception_handling' => array + 'exception_handling' => array ( 'value' => array ( 'debug' => false, // режим отладки 'handled_errors_types' => 4437, // типы обрабатываемых ошибок diff --git a/pages/modules/architecture.md b/pages/modules/architecture.md index c20975d..1b380f5 100644 --- a/pages/modules/architecture.md +++ b/pages/modules/architecture.md @@ -694,7 +694,7 @@ require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/company.module/prolog. /local/modules/company.module/ ├── admin/ │ └── my_page.php -├── lang/ +└── lang/ ├── en/ │ └── admin/ │ └── my_page.php diff --git a/pages/modules/catalog/catalog-settings.md b/pages/modules/catalog/catalog-settings.md index 052bcef..40b2224 100644 --- a/pages/modules/catalog/catalog-settings.md +++ b/pages/modules/catalog/catalog-settings.md @@ -116,11 +116,13 @@ $accessRows = \Bitrix\Catalog\GroupAccessTable::getList([ foreach ($accessRows as $row) { - if ($row['ACCESS'] === 'ACCESS_VIEW') { + if ($row['ACCESS'] === 'ACCESS_VIEW') + { echo "Группа {$row['GROUP_ID']} видит цену\n"; } - if ($row['ACCESS'] === 'ACCESS_BUY') { + if ($row['ACCESS'] === 'ACCESS_BUY') + { echo "Группа {$row['GROUP_ID']} может покупать по этой цене\n"; } } diff --git a/pages/modules/iblocks/api.md b/pages/modules/iblocks/api.md index 1bf8e6b..4762454 100644 --- a/pages/modules/iblocks/api.md +++ b/pages/modules/iblocks/api.md @@ -181,8 +181,8 @@ $result = $authorProp->Add([ 'IBLOCK_ID' => $iblockId, 'NAME' => 'Автор', 'CODE' => 'AUTHOR', - 'PROPERTY_TYPE' => 'S', // строка - 'MULTIPLE' => 'N', // одно значение + 'PROPERTY_TYPE' => 'S', // строка + 'MULTIPLE' => 'N', // одно значение ]); if (!$result) @@ -198,7 +198,7 @@ $result = $tagsProp->Add([ 'NAME' => 'Теги', 'CODE' => 'TAGS', 'PROPERTY_TYPE' => 'S', - 'MULTIPLE' => 'Y', // несколько значений + 'MULTIPLE' => 'Y', // несколько значений ]); if (!$result) @@ -218,8 +218,8 @@ $property->Add([ 'IBLOCK_ID' => $iblockId, 'NAME' => 'Фото', 'CODE' => 'PHOTO', - 'PROPERTY_TYPE' => 'F', // файл - 'MULTIPLE' => 'N', // один файл + 'PROPERTY_TYPE' => 'F', // файл + 'MULTIPLE' => 'N', // один файл ]); // Галерея — несколько файлов @@ -246,7 +246,7 @@ $result = $property->Add([ 'IBLOCK_ID' => $iblockId, 'NAME' => 'Источник', 'CODE' => 'SOURCE', - 'PROPERTY_TYPE' => 'L', // список + 'PROPERTY_TYPE' => 'L', // список 'MULTIPLE' => 'N', ]); @@ -264,7 +264,7 @@ $enum->Add([ 'PROPERTY_ID' => $propId, 'VALUE' => 'РИА Новости', 'SORT' => 10, - 'XML_ID' => 'ria', // уникальный код, только латиница + 'XML_ID' => 'ria', // уникальный код, только латиница ]); $enum->Add([ @@ -293,8 +293,8 @@ $result = $property->Add([ 'IBLOCK_ID' => $iblockId, 'NAME' => 'Итог', 'CODE' => 'SUMMARY', - 'PROPERTY_TYPE' => 'S', // строка - 'USER_TYPE' => 'HTML', // специальное поле для редактирования текста или кода HTML + 'PROPERTY_TYPE' => 'S', // строка + 'USER_TYPE' => 'HTML', // специальное поле для редактирования текста или кода HTML 'MULTIPLE' => 'N', ]); @@ -330,8 +330,8 @@ $result = $property->Add([ 'IBLOCK_ID' => $iblockId, 'NAME' => 'Рубрика', 'CODE' => 'CATEGORY', - 'PROPERTY_TYPE' => 'S', // в базе — строка, хранит UF_XML_ID - 'USER_TYPE' => 'directory', // выпадающий список из Highload-блока + 'PROPERTY_TYPE' => 'S', // в базе — строка, хранит UF_XML_ID + 'USER_TYPE' => 'directory', // выпадающий список из Highload-блока 'MULTIPLE' => 'N', 'USER_TYPE_SETTINGS' => [ 'TABLE_NAME' => 'b_news_categories', // название таблицы Highload-блока @@ -398,7 +398,8 @@ $section = $sectionNewsClass::createObject() ->setName('Мероприятия') ->setCode('events') ->setActive(true) - ->save(); + ->save() +; $eventsSectionId = $section->getId(); ``` @@ -413,7 +414,8 @@ $section = $sectionNewsClass::query() ->setSelect(['NAME', 'ACTIVE']) ->where('CODE', 'events') ->setLimit(1) - ->fetchObject(); + ->fetchObject() +; if ($section) { echo "Раздел: " . $section->getName(); // Мероприятия @@ -433,7 +435,8 @@ $parentSection = $sectionNewsClass::query() ->setSelect(['ID']) ->where('CODE', 'events') ->setLimit(1) - ->fetchObject(); + ->fetchObject() +; if ($parentSection) { @@ -444,7 +447,8 @@ if ($parentSection) ->setCode('exhibitions') ->setIblockSectionId($parentSection->getId()) // привязка к родителю ->setActive(true) - ->save(); + ->save() + ; $exhibitionSectionId = $exhibitionSection->getId(); } @@ -460,7 +464,9 @@ $sections = $sectionNewsClass::query() ->where('ACTIVE', 'Y') ->setOrder(['NAME' => 'ASC']) ->setLimit(10) - ->fetchCollection(); + ->fetchCollection() +; + foreach ($sections as $item) { echo $item->getName() . "\n"; @@ -481,7 +487,8 @@ $exhibitionSection = $sectionNewsClass::query() ]) ->where('CODE', 'exhibitions') ->setLimit(1) - ->fetchObject(); + ->fetchObject() +; if ($exhibitionSection) { @@ -512,13 +519,15 @@ if ($exhibitionSection) $exhibitionSection = $sectionNewsClass::query() ->where('CODE', 'exhibitions') ->setLimit(1) - ->fetchObject(); + ->fetchObject() +; if ($exhibitionSection) { $exhibitionSection ->setName('Выставки 2025-2026') // изменим название раздела - ->setActive(false); // и деактивируем его + ->setActive(false) // и деактивируем его + ; $result = $exhibitionSection->save(); @@ -551,7 +560,8 @@ $conferenceSection = $sectionNewsClass::createObject() ->setCode('conferences') ->set('UF_MANAGER', 'Ирина Сидорова') // ← значение UF-поля ->setActive(true) - ->save(); + ->save() +; ``` ### Получить пользовательские поля раздела @@ -563,7 +573,8 @@ $conferenceSection = $sectionNewsClass::query() ->setSelect(['ID', 'NAME', 'UF_*']) // загружаем все UF-поля ->where('CODE', 'conferences') ->setLimit(1) - ->fetchObject(); + ->fetchObject() +; if ($conferenceSection) { @@ -600,7 +611,8 @@ ORM-метод `$section->delete()` применяйте для специфич $conferenceSection = $sectionNewsClass::query() ->where('CODE', 'conferences') ->setLimit(1) - ->fetchObject(); + ->fetchObject() +; if ($conferenceSection) { @@ -655,7 +667,8 @@ $element = $elementNewsClass::createObject() ->setName('Обновление системы безопасности') ->setCode('security-update') ->setActive(true) - ->set('AUTHOR', 'Ирина Петрова'); + ->set('AUTHOR', 'Ирина Петрова') +; $result = $element->save(); @@ -689,7 +702,8 @@ $parentSection = $sectionNewsClass::query() ->setSelect(['ID']) ->where('CODE', 'events') ->setLimit(1) - ->fetchObject(); + ->fetchObject() +; if ($parentSection) { @@ -698,7 +712,8 @@ if ($parentSection) ->setCode('cybersec-conf-2026') ->setActive(true) ->setIblockSectionId($parentSection->getId()) // привязка к разделу - ->set('AUTHOR', 'Иван Сидоров'); + ->set('AUTHOR', 'Иван Сидоров') + ; $element->save(); } @@ -726,8 +741,9 @@ if ($parentSection) $element = $elementNewsClass::createObject() ->setName('Новость с автором и источником') ->setCode('news-author-source') - ->set('AUTHOR', 'Светлана Пирогова') // строка — текст напрямую - ->set('SOURCE', 1); // список — идентификатор значения «РИА Новости» + ->set('AUTHOR', 'Светлана Пирогова') // строка — текст напрямую + ->set('SOURCE', 1) // список — идентификатор значения «РИА Новости» +; $element->save(); ``` @@ -742,7 +758,8 @@ $element = $elementNewsClass::createObject() ->setCode('news-tags') ->addTo('TAGS', 'безопасность') ->addTo('TAGS', 'обновление') - ->addTo('TAGS', '2026'); + ->addTo('TAGS', '2026') +; $element->save(); ``` @@ -798,7 +815,8 @@ $element = $elementNewsClass::createObject() ->setName('Новость с изображениями') ->setCode('news-image') ->set('PHOTO', new PropertyValue($photoId, 'Главное фото')) - ->addTo('GALLERY', new PropertyValue($otherId, 'Дополнительный снимок')); + ->addTo('GALLERY', new PropertyValue($otherId, 'Дополнительный снимок')) +; $element->save(); ``` @@ -816,7 +834,8 @@ $element->save(); ```php $element = $elementNewsClass::createObject() ->setName('Новость с итогом') - ->set('SUMMARY', '

Вывод: система защищена от уязвимостей CVE-2026-XXXX.

'); + ->set('SUMMARY', '

Вывод: система защищена от уязвимостей CVE-2026-XXXX.

') +; $element->save(); ``` @@ -839,7 +858,8 @@ $safeHtml = \Bitrix\Main\Text\HtmlFilter::getHtmlEncoder()->encode($userInput); $element = $elementNewsClass::createObject() ->setName('Новость по кибербезопасности') ->setCode('news-cybersec') - ->set('CATEGORY', 'cybersec'); + ->set('CATEGORY', 'cybersec') +; $element->save(); ``` @@ -876,7 +896,8 @@ $element->save(); $element = $elementNewsClass::query() ->where('CODE', 'security-update') ->setLimit(1) - ->fetchObject(); + ->fetchObject() +; if ($element) { @@ -892,15 +913,16 @@ if ($element) $element = $elementNewsClass::query() ->where('CODE', 'news-author-source') ->setLimit(1) - ->fetchObject(); + ->fetchObject() +; echo $element->get('AUTHOR')?->getValue(); // Светлана Пирогова $source = $element->get('SOURCE'); if ($source) { - echo $source->getItem()->getValue(); // РИА Новости - echo $source->getItem()->getXmlId(); // ria + echo $source->getItem()->getValue(); // РИА Новости + echo $source->getItem()->getXmlId(); // ria } ``` @@ -912,7 +934,8 @@ if ($source) $element = $elementNewsClass::query() ->where('CODE', 'news-tags') ->setLimit(1) - ->fetchObject(); + ->fetchObject() +; foreach ($element->get('TAGS')->getAll() as $tag) { @@ -930,7 +953,8 @@ foreach ($element->get('TAGS')->getAll() as $tag) $element = $elementNewsClass::query() ->where('CODE', 'news-image') ->setLimit(1) - ->fetchObject(); + ->fetchObject() +; $photo = $element->get('PHOTO'); if ($photo) @@ -949,7 +973,8 @@ $element = $elementNewsClass::query() ->setSelect(['ID', 'NAME', 'GALLERY']) ->where('CODE', 'news-image') ->setLimit(1) - ->fetchObject(); + ->fetchObject() +; if ($element) { @@ -1143,14 +1168,16 @@ foreach ($elements as $element) ```php $element = $elementNewsClass::query() ->where('CODE', 'security-update') - ->fetchObject(); + ->fetchObject() +; if ($element) { $element ->setName('Критическое обновление') ->removeAll('TAGS') - ->addTo('TAGS', 'критическое'); + ->addTo('TAGS', 'критическое') + ; $element->save(); } @@ -1173,7 +1200,8 @@ if ($element) ```php $element = $elementNewsClass::query() ->where('CODE', 'security-update') // символьный код элемента Обновление системы безопасности - ->fetchObject(); + ->fetchObject() +; if ($element) { @@ -1344,15 +1372,16 @@ $news = $elementNewsClass::query() ->setSelect([ 'ID', 'NAME', - 'AUTHOR', // строка — напрямую - 'SOURCE.VALUE', // список — VALUE, а не SOURCE + 'AUTHOR', // строка — напрямую + 'SOURCE.VALUE', // список — VALUE, а не SOURCE 'DATE_ACTIVE_FROM', 'SECTION_' => 'IBLOCK_SECTION', // подгружаем раздел за один запрос ]) ->where('ACTIVE', 'Y') ->setOrder(['DATE_ACTIVE_FROM' => 'DESC']) ->setLimit(10) - ->fetchCollection(); + ->fetchCollection() + ; foreach ($news as $item) { @@ -1378,12 +1407,13 @@ $element = $elementNewsClass::query() ->setSelect([ 'ID', 'NAME', 'AUTHOR', 'PHOTO.VALUE', 'PHOTO.DESCRIPTION', - 'SUMMARY', // HTML-свойство + 'SUMMARY', // HTML-свойство 'SECTION_' => 'IBLOCK_SECTION', ]) ->where('CODE', $arParams['ELEMENT_CODE'] ?? '') ->setLimit(1) - ->fetchObject(); + ->fetchObject() + ; if ($element) { @@ -1425,7 +1455,8 @@ $elements = $elementNewsClass::query() ->setSelect(['ID', 'NAME', 'DETAIL_TEXT']) ->where('ACTIVE', 'Y') ->setLimit(5) - ->fetchCollection(); + ->fetchCollection() +; foreach ($elements as $item) { @@ -1438,7 +1469,9 @@ foreach ($elements as $item) { $preview .= '…'; } - } else { + } + else + { $preview = ''; } @@ -1457,7 +1490,8 @@ foreach ($elements as $item) $current = $elementNewsClass::query() ->setSelect(['ID', 'SOURCE']) ->where('CODE', $arParams['ELEMENT_CODE']) - ->fetchObject(); + ->fetchObject() +; if (!$current) return; @@ -1467,10 +1501,11 @@ if (!$sourceId) return; $similar = $elementNewsClass::query() ->setSelect(['ID', 'NAME', 'CODE']) ->where('ACTIVE', 'Y') - ->where('SOURCE.VALUE', $sourceId) // фильтр по идентификатору источника + ->where('SOURCE.VALUE', $sourceId) // фильтр по идентификатору источника ->whereNot('ID', $current->getId()) ->setLimit(5) - ->fetchCollection(); + ->fetchCollection() +; $arResult['MORE_FROM_SOURCE'] = []; foreach ($similar as $item) diff --git a/pages/modules/iblocks/architecture.md b/pages/modules/iblocks/architecture.md index 84ac0f5..1292efb 100644 --- a/pages/modules/iblocks/architecture.md +++ b/pages/modules/iblocks/architecture.md @@ -125,7 +125,8 @@ $items = ElementClothesTable::query() ) ) ->setSelect(['ID', 'NAME', 'NAME_LENGTH']) - ->fetchAll(); + ->fetchAll() +; ``` В результате в выборке появится поле `NAME_LENGTH`. Оно действует только в этом запросе и не меняет карту класса. diff --git a/pages/modules/iblocks/overview.md b/pages/modules/iblocks/overview.md index 28dc274..5d9f767 100644 --- a/pages/modules/iblocks/overview.md +++ b/pages/modules/iblocks/overview.md @@ -141,7 +141,8 @@ $element->save(); // Получить элемент по ID $existingElement = $entityClass::getByPrimary($element->getId()) - ->fetchObject(); + ->fetchObject() +; if ($existingElement) { diff --git a/pages/modules/iblocks/performance.md b/pages/modules/iblocks/performance.md index 80ecaaa..a7fbac6 100644 --- a/pages/modules/iblocks/performance.md +++ b/pages/modules/iblocks/performance.md @@ -76,7 +76,9 @@ function updateActiveElementsStat() if ($cache->InitCache(3600, 'active_elements_count', '/stats/')) { $count = $cache->GetVars()['count']; - } else { + } + else + { if ($cache->StartDataCache()) { // Выбираем только ID и дату начала активности @@ -217,7 +219,8 @@ CIBlockElement::GetList([], [ // query() автоматически использует %= \Bitrix\Iblock\ElementTable::query() ->where('CODE', 'news') - ->exec(); + ->exec() +; ``` ### Проанализировать SQL-запросы @@ -318,7 +321,8 @@ $res = CIBlockElement::GetList([], $filter, false, false, $arSelect); ```php $element = \Bitrix\Iblock\Elements\ElementNewsTable::createObject() ->setName('Новость') - ->set('SOURCE', 105); // 105 — ID варианта в b_iblock_property_enum + ->set('SOURCE', 105) // 105 — ID варианта в b_iblock_property_enum +; $element->save(); ``` @@ -331,7 +335,8 @@ $element->save(); $element = \Bitrix\Iblock\Elements\ElementNewsTable::createObject() ->setName('Обзор товара') // RELATED_ITEM — код свойства типа Привязка к элементу - ->set('RELATED_ITEM', 789); // 789 — ID элемента в инфоблоке Товары + ->set('RELATED_ITEM', 789) // 789 — ID элемента в инфоблоке Товары +; $element->save(); ``` @@ -340,7 +345,8 @@ $element->save(); ```php $element = \Bitrix\Iblock\Elements\ElementNewsTable::createObject() ->setName('Обзор') - ->set('RELATED_ITEM', 'product-2026'); // XML_ID из инфоблока Товары + ->set('RELATED_ITEM', 'product-2026') // XML_ID из инфоблока Товары +; $element->save(); ``` diff --git a/pages/orm/annotations.md b/pages/orm/annotations.md index f039066..830ca6c 100644 --- a/pages/orm/annotations.md +++ b/pages/orm/annotations.md @@ -33,7 +33,8 @@ namespace Bitrix\Main { * @method mixed get($fieldName) * ... */ - class EO_User extends \Bitrix\Main\ORM\Objectify\EntityObject { + class EO_User extends \Bitrix\Main\ORM\Objectify\EntityObject + { /* @var \Bitrix\Main\UserTable */ static public $dataClass = '\Bitrix\Main\UserTable'; /** @@ -61,8 +62,6 @@ namespace Bitrix\Main { ```php class MyClass { - // ... - private function getName(EO_User $user): string { return CUser::FormatName( @@ -74,6 +73,7 @@ class MyClass ], ); } + // ... } ``` diff --git a/pages/orm/collections.md b/pages/orm/collections.md index 2d9f885..968cb8d 100644 --- a/pages/orm/collections.md +++ b/pages/orm/collections.md @@ -17,7 +17,8 @@ description: 'Коллекции. ORM Bitrix Framework: ключевые кон ```php $books = \Bitrix\Main\Test\Typography\BookTable::getList() - ->fetchCollection(); + ->fetchCollection() +; ``` `$books` — это коллекция объектов класса `Book` с методами для групповых операций. @@ -31,6 +32,7 @@ $books = \Bitrix\Main\Test\Typography\BookTable::getList() ```php // Файл bitrix/modules/main/lib/test/typography/books.php namespace Bitrix\Main\Test\Typography; + class Books extends EO_Book_Collection { } @@ -41,13 +43,14 @@ class Books extends EO_Book_Collection ```php // Файл bitrix/modules/main/lib/test/typography/booktable.php namespace Bitrix\Main\Test\Typography; + class BookTable extends Bitrix\Main\ORM\Data\DataManager { public static function getCollectionClass() { return Books::class; } - //... + // ... } ``` @@ -67,7 +70,8 @@ class Books extends EO_Book_Collection ```php $books = \Bitrix\Main\Test\Typography\BookTable::getList() - ->fetchCollection(); + ->fetchCollection() +; foreach ($books as $book) { // ... @@ -80,7 +84,8 @@ foreach ($books as $book) ```php $books = \Bitrix\Main\Test\Typography\BookTable::getList() - ->fetchCollection(); + ->fetchCollection() +; $bookObjects = $books->getAll(); echo $bookObjects[0]->getId(); // выведет значение ID первого объекта @@ -98,13 +103,15 @@ $books = $bookCollection->collectValues(); ```php // Пример с простым первичным ключом $books = \Bitrix\Main\Test\Typography\BookTable::getList() - ->fetchCollection(); + ->fetchCollection() +; $book = $books->getByPrimary(1); // книга с ID=1 // Пример с составным первичным ключом $booksToAuthor = \Bitrix\Main\Test\Typography\BookAuthorTable::getList() - ->fetchCollection(); + ->fetchCollection() +; $bookToAuthor = $booksToAuthor->getByPrimary(['BOOK_ID' => 2, 'AUTHOR_ID' => 18]); // объект отношения книги ID=2 с автором ID=18 ``` @@ -121,6 +128,7 @@ $books = \Bitrix\Main\Test\Typography\BookTable::query() ->whereIn('ID', [2, 3, 4]) ->fetchCollection() ; + var_dump($books->has($book1)); // false var_dump($books->has($book2)); // true ``` @@ -133,6 +141,7 @@ $books = \Bitrix\Main\Test\Typography\BookTable::query() ->whereIn('ID', [2, 3, 4]) ->fetchCollection() ; + var_dump($books->hasByPrimary(1)); // false var_dump($books->hasByPrimary(2)); // true ``` @@ -145,6 +154,7 @@ $books = \Bitrix\Main\Test\Typography\BookTable::query() ->whereIn('ID', [2, 3, 4]) ->fetchCollection() ; + $isEmpty = $books->isEmpty(); ``` @@ -159,6 +169,7 @@ $books = \Bitrix\Main\Test\Typography\BookTable::query() ->whereIn('ID', [2, 3, 4]) ->fetchCollection() ; + $books->add($book1); // или $books[] = $book1; @@ -171,7 +182,8 @@ $books[] = $book1; ```php $book1 = \Bitrix\Main\Test\Typography\Book::wakeUp(1); $books = \Bitrix\Main\Test\Typography\BookTable::getList() - ->fetchCollection(); + ->fetchCollection() +; $books->remove($book1); // удалится книга с ID=1 $books->removeByPrimary(2); @@ -187,8 +199,8 @@ $books->removeByPrimary(2); Метод `save()` сохраняет новые объекты одним запросом к базе данных. ```php -use \Bitrix\Main\Test\Typography\Books; -use \Bitrix\Main\Test\Typography\Book; +use Bitrix\Main\Test\Typography\Books; +use Bitrix\Main\Test\Typography\Book; $books = new Books; $books[] = (new Book)->setTitle('Title 112'); @@ -197,6 +209,7 @@ $books[] = (new Book) ->setTitle('Title 114') ->setIsbn('114-000') ; + $books->save(true); // INSERT INTO ... (`TITLE`, `ISBN`) VALUES // ('Title 112', DEFAULT), @@ -211,8 +224,9 @@ $books->save(true); Метод `save()` сохраняет измененные объекты одним запросом `UPDATE`. ```php -use \Bitrix\Main\Test\Typography\PublisherTable; -use \Bitrix\Main\Test\Typography\BookTable; +use Bitrix\Main\Test\Typography\PublisherTable; +use Bitrix\Main\Test\Typography\BookTable; + $books = BookTable::getList()->fetchCollection(); $publisher = PublisherTable::wakeUpObject(254); foreach ($books as $book) @@ -273,9 +287,9 @@ $books->fill(\Bitrix\Main\ORM\Fields\FieldTypeMask::FLAT); ```php $books = \Bitrix\Main\Test\Typography\BookTable::getList() - ->fetchCollection(); -$books->walk(static function($book) -{ + ->fetchCollection() +; +$books->walk(static function($book) { if ($book->getPrice() > 1000) { $book->setActive(false); @@ -292,8 +306,7 @@ $saveResult = \Bitrix\Main\Test\Typography\BookTable::query() ->addSelect('*') ->where('> PRICE', 1000) ->fetchCollection() - ->walk(static function($book) - { + ->walk(static function($book) { $book->setActive(false); }) ->save() @@ -306,7 +319,8 @@ $saveResult = \Bitrix\Main\Test\Typography\BookTable::query() ```php $books = \Bitrix\Main\Test\Typography\BookTable::getList() - ->fetchCollection(); + ->fetchCollection() +; $titles = $books->getTitleList(); ``` diff --git a/pages/orm/entity-operations.md b/pages/orm/entity-operations.md index faedefe..ef27871 100644 --- a/pages/orm/entity-operations.md +++ b/pages/orm/entity-operations.md @@ -131,8 +131,6 @@ $em->addEventHandler( ```php class BookTable extends Entity\DataManager { - ... - public static function onBeforeAdd(Entity\Event $event) { $result = new Entity\EventResult; @@ -146,6 +144,8 @@ class BookTable extends Entity\DataManager return $result; } + + // ... } ``` @@ -180,7 +180,7 @@ class BookTable extends Entity\DataManager // } // }, new Entity\Validator\RegExp('/\d{13}/'), // Валидатор, проверяющий, что значение содержит 13 цифр подряд - ... + // ... ]; } ``` @@ -216,7 +216,7 @@ public static function onBeforeUpdate(Entity\Event $event) if (isset($data['ISBN'])) { - // Получает объект поля ISBN и выдает сообщение об ошибке + // Получает объект поля ISBN и выдает сообщение об ошибке $result->addError(new Entity\FieldError( $event->getEntity()->getField('ISBN'), 'Запрещено менять ISBN код у существующих книг' @@ -235,8 +235,7 @@ public static function onBeforeUpdate(Entity\Event $event) $result = new Entity\EventResult; $data = $event->getParameter("fields"); - if (...) - { // Здесь должна быть ваша логика комплексной проверки данных + if (...) { // Здесь должна быть ваша логика комплексной проверки данных $result->addError(new Entity\EntityError( 'Невозможно обновить запись' )); @@ -337,8 +336,7 @@ BookTable::update($id, [ // Обновление записи в таблице ```php // Вызов с проверкой успешности выполнения запроса $result = BookTable::update(...); // Выполнение обновления и сохранение результата -if (!$result->isSuccess()) -{ // Проверка успешности выполнения +if (!$result->isSuccess()) { // Проверка успешности выполнения // обработка ошибки // Здесь можно добавить код для обработки ошибок, например, логирование или уведомление пользователя } @@ -353,6 +351,7 @@ BookTable::update(...); // Обновление записи без провер ```php namespace SomePartner\MyBooksCatalog; // Определение пространства имен для организации кода + use Bitrix\Main\Entity; // Импорт класса Entity для работы с ORM use Bitrix\Main\Type; // Импорт класса Type для работы с типами данных @@ -415,8 +414,7 @@ class BookTable extends Entity\DataManager // Класс BookTable наслед { $result = new Entity\EventResult; // Создание объекта для результата события $data = $event->getParameter("fields"); // Получение данных полей из события - if (isset($data['ISBN'])) // Проверка наличия поля ISBN - { + if (isset($data['ISBN'])) { // Проверка наличия поля ISBN $cleanIsbn = str_replace('-', '', $data['ISBN']); // Удаление дефисов из ISBN $result->modifyFields(array('ISBN' => $cleanIsbn)); // Модификация поля ISBN } diff --git a/pages/orm/entity-relations.md b/pages/orm/entity-relations.md index 17690aa..7c3dcca 100644 --- a/pages/orm/entity-relations.md +++ b/pages/orm/entity-relations.md @@ -198,7 +198,8 @@ Array ( Создадим класс `PublisherTable`, который представляет собой таблицу издательств в базе данных. Этот класс наследуется от `DataManager` — основного класса для работы с данными в Bitrix Framework. ```php -namespace Bitrix\Main\Test\Typography; +namespace Bitrix\Main\Test\Typography; + use Bitrix\Main\ORM\Data\DataManager; // Импорт класса DataManager для работы с данными use Bitrix\Main\ORM\Fields\Relations\OneToMany; // Импорт класса OneToMany для создания связей «один ко многим» @@ -230,7 +231,8 @@ $publisher = \Bitrix\Main\Test\Typography\PublisherTable::getByPrimary(253, [ ])->fetchObject(); // Перебор всех книг, связанных с издательством -foreach ($publisher->getBooks() as $book) { +foreach ($publisher->getBooks() as $book) +{ echo $book->getTitle(); // Вывод названия каждой книги } // Цикл выведет "Title 1" и "Title 2" @@ -249,24 +251,24 @@ $data = \Bitrix\Main\Test\Typography\PublisherTable::getByPrimary(253, [ // Вернет Array ( - [0] => Array ( - [ID] => 253 - [TITLE] => Publisher Title 253 - [BOOK_ID] => 2 - [BOOK_TITLE] => Title 2 - [BOOK_PUBLISHER_ID] => 253 - [BOOK_ISBN] => 456-1-05-586920-1 - [BOOK_IS_ARCHIVED] => N - ) - [1] => Array ( - [ID] => 253 - [TITLE] => Publisher Title 253 - [BOOK_ID] => 1 - [BOOK_TITLE] => Title 1 - [BOOK_PUBLISHER_ID] => 253 - [BOOK_ISBN] => 978-3-16-148410-0 - [BOOK_IS_ARCHIVED] => Y - ) + [0] => Array ( + [ID] => 253 + [TITLE] => Publisher Title 253 + [BOOK_ID] => 2 + [BOOK_TITLE] => Title 2 + [BOOK_PUBLISHER_ID] => 253 + [BOOK_ISBN] => 456-1-05-586920-1 + [BOOK_IS_ARCHIVED] => N + ) + [1] => Array ( + [ID] => 253 + [TITLE] => Publisher Title 253 + [BOOK_ID] => 1 + [BOOK_TITLE] => Title 1 + [BOOK_PUBLISHER_ID] => 253 + [BOOK_ISBN] => 978-3-16-148410-0 + [BOOK_IS_ARCHIVED] => Y + ) ) ``` @@ -277,12 +279,14 @@ Array ( ```php // Инициализация объекта издательства $publisher = \Bitrix\Main\Test\Typography\PublisherTable::getByPrimary(253) - ->fetchObject(); + ->fetchObject() +; // Метод getByPrimary загружает объект издательства с первичным ключом 253 из базы данных // Инициализация объекта книги $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(2) - ->fetchObject(); + ->fetchObject() +; // Метод getByPrimary загружает объект книги с первичным ключом 2 из базы данных // Добавление книги в коллекцию книг издательства @@ -456,7 +460,8 @@ class CoverTable extends DataManager // Класс CoverTable наследует Для связи «один к одному» между таблицами `BookTable` и `CoverTable` используется поле `Reference`. Это поле позволяет создать связь между таблицами через указанные условия соединения. ```php -namespace Bitrix\Main\Test\Typography; +namespace Bitrix\Main\Test\Typography; + use Bitrix\Main\ORM\Fields\Relations\Reference; // Импорт класса Reference для создания связей между таблицами use Bitrix\Main\ORM\Query\Join; // Импорт класса Join для определения условий соединения @@ -733,10 +738,12 @@ class ... extends \Bitrix\Main\ORM\Data\DataManager ```php $author = \Bitrix\Main\Test\Typography\AuthorTable::getByPrimary(17) - ->fetchObject(); // Получаем объект автора с ID 17 + ->fetchObject() // Получаем объект автора с ID 17 +; $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); // Получаем объект книги с ID 1 + ->fetchObject() // Получаем объект книги с ID 1 +; $author->addToBooks($book); // Добавляем книгу к автору $author->save(); // Сохраняем изменения @@ -753,7 +760,8 @@ $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(2, [ 'select' => ['*', 'AUTHORS'] // Выбираем все поля книги и связанных авторов ])->fetchObject(); -foreach ($book->getAuthors() as $author) { +foreach ($book->getAuthors() as $author) +{ echo $author->getLastName(); // Выводим фамилию каждого автора } // Цикл выведет "Last name 17" и "Last name 18" @@ -765,10 +773,12 @@ foreach ($book->getAuthors() as $author) { ```php $author = \Bitrix\Main\Test\Typography\AuthorTable::getByPrimary(17) - ->fetchObject(); // Получаем объект автора с ID 17 + ->fetchObject() // Получаем объект автора с ID 17 +; $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); // Получаем объект книги с ID 1 + ->fetchObject() // Получаем объект книги с ID 1 +; $author->addToBooks($book); // Добавляем книгу к автору $author->save(); // Сохраняем изменения @@ -778,10 +788,12 @@ $author->save(); // Сохраняем изменения ```php $author = \Bitrix\Main\Test\Typography\AuthorTable::getByPrimary(17) - ->fetchObject(); // Получаем объект автора с ID 17 + ->fetchObject() // Получаем объект автора с ID 17 +; $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); // Получаем объект книги с ID 1 + ->fetchObject() // Получаем объект книги с ID 1 +; $book->addToAuthors($author); // Добавляем автора к книге $book->save(); // Сохраняем изменения @@ -855,15 +867,18 @@ class StoreBookTable extends DataManager ```php // Объект книги $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); + ->fetchObject() +; // Объект магазина $store = \Bitrix\Main\Test\Typography\StoreTable::getByPrimary(34) - ->fetchObject(); + ->fetchObject() +; // Новый объект связи книги с магазином $item = \Bitrix\Main\Test\Typography\StoreBookTable::createObject() - ->setBook($book) - ->setStore($store) - ->setQuantity(5); + ->setBook($book) + ->setStore($store) + ->setQuantity(5) +; // Сохранение $item->save(); ``` @@ -873,7 +888,8 @@ $item->save(); ```php // Объект существующей связи $item = \Bitrix\Main\Test\Typography\StoreBookTable::getByPrimary([ - 'STORE_ID' => 33, 'BOOK_ID' => 2 + 'STORE_ID' => 33, + 'BOOK_ID' => 2, ])->fetchObject(); // Обновление количества $item->setQuantity(12); @@ -886,7 +902,8 @@ $item->save(); ```php // Объект существующей связи $item = \Bitrix\Main\Test\Typography\StoreBookTable::getByPrimary([ - 'STORE_ID' => 33, 'BOOK_ID' => 2 + 'STORE_ID' => 33, + 'BOOK_ID' => 2, ])->fetchObject(); // Удаление $item->delete(); @@ -897,16 +914,18 @@ $item->delete(); ```php // Добавление записи \Bitrix\Main\Test\Typography\StoreBookTable::add([ - 'STORE_ID' => 34, 'BOOK_ID' => 1, 'QUANTITY' => 5 + 'STORE_ID' => 34, + 'BOOK_ID' => 1, + 'QUANTITY' => 5, ]); // Обновление записи \Bitrix\Main\Test\Typography\StoreBookTable::update( - ['STORE_ID' => 34, 'BOOK_ID' => 1], - ['QUANTITY' => 12] + ['STORE_ID' => 34, 'BOOK_ID' => 1], + ['QUANTITY' => 12] ); // Удаление записи \Bitrix\Main\Test\Typography\StoreBookTable::delete( - ['STORE_ID' => 34, 'BOOK_ID' => 1] + ['STORE_ID' => 34, 'BOOK_ID' => 1] ); ``` @@ -967,8 +986,7 @@ $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1, [ 'select' => ['*', 'STORE_ITEMS'] // Выбираем все поля книги и связанные записи о наличии в магазинах ])->fetchObject(); -foreach ($book->getStoreItems() as $storeItem) // Перебираем все связанные записи о наличии книги в магазинах -{ +foreach ($book->getStoreItems() as $storeItem) { // Перебираем все связанные записи о наличии книги в магазинах printf( 'store "%s" has %s of book "%s"', // Форматируем строку для вывода информации $storeItem->getStoreId(), // Получаем ID магазина diff --git a/pages/orm/objects.md b/pages/orm/objects.md index c8b5486..d21b98c 100644 --- a/pages/orm/objects.md +++ b/pages/orm/objects.md @@ -9,7 +9,8 @@ description: 'Объекты. ORM Bitrix Framework: ключевые конце ```php $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); + ->fetchObject() +; ``` Теперь `$book` — это объект сущности `Book`, который предоставляет методы для работы с данными книги и ее связями с другими сущностями. Методы объекта можно использовать для получения и изменения данных, например, `$book->getTitle()` для получения названия книги или `$book->setTitle('New Title')` для его изменения. @@ -46,7 +47,7 @@ class BookTable extends Bitrix\Main\ORM\Data\DataManager { return Book::class; } - //... + // ... } ``` @@ -113,7 +114,8 @@ class Book extends EO_Book } $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); + ->fetchObject() +; echo $book->getTitle(); // 'custom title' echo $book->get('TITLE'); // 'custom title' @@ -133,7 +135,8 @@ echo $book->get('TITLE'); // 'custom title' ```php $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); + ->fetchObject() +; var_dump($book->getId()); // int 1 var_dump($book->getTitle()); // string 'Title 1' (length=7) ``` @@ -145,7 +148,8 @@ var_dump($book->getTitle()); // string 'Title 1' (length=7) // ->configureValues('N', 'Y'), $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); + ->fetchObject() +; var_dump($book->getIsArchived()); // boolean true // При установке значений также ожидается boolean @@ -162,7 +166,8 @@ $book->setIsArchived(false); ```php $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); + ->fetchObject() +; $title = $book->getTitle(); ``` @@ -172,7 +177,8 @@ $title = $book->getTitle(); ```php $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); + ->fetchObject() +; $title = $book->requireTitle(); ``` @@ -180,7 +186,8 @@ $title = $book->requireTitle(); ```php $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1, ['select' => ['ID', 'PUBLISHER_ID', 'ISBN']]) - ->fetchObject(); + ->fetchObject() +; $title = $book->requireTitle(); // SystemException: "TITLE value is required for further operations" ``` @@ -191,7 +198,8 @@ $title = $book->requireTitle(); ```php $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); + ->fetchObject() +; echo $book->getTitle(); // "Title 1" $book->setTitle("New title"); echo $book->getTitle(); // "New title" @@ -213,7 +221,8 @@ $title = $book->remindActual($fieldName); ```php $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); + ->fetchObject() +; $primary = $book->primary; // ['ID' => 1] $id = $book->getId(); // 1 ``` @@ -224,7 +233,8 @@ $id = $book->getId(); // 1 ```php $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); + ->fetchObject() +; $values = $book->collectValues(); ``` @@ -263,7 +273,8 @@ $author = \Bitrix\Main\Test\Typography\AuthorTable::query() ->addSelect('ID') ->addSelect('FULL_NAME') ->where('ID', 17) - ->fetchObject(); + ->fetchObject() +; echo $author->get('FULL_NAME'); // 'Name 17 Last name 17' ``` @@ -279,7 +290,8 @@ echo $author->get('FULL_NAME'); // 'Name 17 Last name 17' ```php $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); + ->fetchObject() +; $book->setTitle("New title"); ``` @@ -300,7 +312,8 @@ $book->remindActualTitle(); // актуальное значение ```php $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); + ->fetchObject() +; echo $book->getTitle(); // "Title 1" $book->setTitle("New title"); echo $book->getTitle(); // "New title" @@ -314,7 +327,8 @@ echo $book->getTitle(); // "Title 1" ```php $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); + ->fetchObject() +; echo $book->getTitle(); // "Title 1" $book->unsetTitle(); echo $book->getTitle(); // null @@ -340,7 +354,7 @@ $book->unset($fieldName); Метод `isFilled` проверяет, содержит ли объект актуальное значение из базы данных. ```php -use \Bitrix\Main\Test\Typography\Book; +use Bitrix\Main\Test\Typography\Book; // актуальными считаются значения из методов fetch* и wakeUp // в примере при инициализации объекта передается только первичный ключ $book = Book::wakeUp(1); @@ -354,7 +368,7 @@ var_dump($book->isTitleFilled()); // true Метод `isChanged` определяет, было ли установлено новое значение в течение сеанса. ```php -use \Bitrix\Main\Test\Typography\Book; +use Bitrix\Main\Test\Typography\Book; // объект может иметь исходное значение, а может и не иметь // это не повлияет на дальнейшее поведение $book = Book::wakeUp(['ID' => 1, 'TITLE' => 'Title 1']); @@ -370,7 +384,7 @@ var_dump($book->isTitleChanged()); // true Метод `has` проверяет, есть ли в объекте какое-либо значение поля — актуальное из базы данных или установленное в сеансе. Это эквивалентно `isFilled() || isChanged()`. ```php -use \Bitrix\Main\Test\Typography\Book; +use Bitrix\Main\Test\Typography\Book; $book = Book::wakeUp(['ID' => 1, 'TITLE' => 'Title 1']); $book->setIsArchived(true); @@ -394,8 +408,8 @@ var_dump($book->hasIsbn()); // false Переход между состояниями происходит автоматически на основе изменений данных. Состояние объекта можно проверить с помощью публичного read-only свойства `state` и констант класса `\Bitrix\Main\ORM\Objectify\State`. ```php -use \Bitrix\Main\Test\Typography\Book; -use \Bitrix\Main\ORM\Objectify\State; +use Bitrix\Main\Test\Typography\Book; +use Bitrix\Main\ORM\Objectify\State; $book = new Book; $book->setTitle('New title'); @@ -417,7 +431,8 @@ var_dump($book->state === State::DELETED); // true ```php $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); + ->fetchObject() +; $book->setTitle("New title"); $book->save(); ``` @@ -432,7 +447,8 @@ $book->save(); ```php $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); + ->fetchObject() +; echo $book->remindActualTitle(); // "Title 1" $book->setTitle("New title"); echo $book->remindActualTitle(); // "Title 1" @@ -482,7 +498,8 @@ echo $book->remindActualTitle(); // "New title" ```php // Удаление записи $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(1) - ->fetchObject(); + ->fetchObject() +; $book->delete(); // Удаление по primary ключу @@ -608,10 +625,12 @@ $author->fill( ```php // Инициализация издателя $publisher = \Bitrix\Main\Test\Typography\PublisherTable::getByPrimary(253) - ->fetchObject(); + ->fetchObject() +; // Инициализация книги $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(2) - ->fetchObject(); + ->fetchObject() +; // Добавление книги в коллекцию отношения $publisher->addToBooks($book); // Сохранение @@ -627,10 +646,12 @@ $publisher->save(); ```php // Инициализация издателя $publisher = \Bitrix\Main\Test\Typography\PublisherTable::getByPrimary(253) - ->fetchObject(); + ->fetchObject() +; // Инициализация книги $book = \Bitrix\Main\Test\Typography\BookTable::getByPrimary(2) - ->fetchObject(); + ->fetchObject() +; // Удаление одной конкретной книги издателя $publisher->removeFromBooks($book); // Сохранение @@ -646,7 +667,8 @@ $publisher->save(); ```php // Инициализация издателя $publisher = \Bitrix\Main\Test\Typography\PublisherTable::getByPrimary(253) - ->fetchObject(); + ->fetchObject() +; // Удаление всех книг издателя $publisher->removeAllBooks(); @@ -697,7 +719,8 @@ $author = \Bitrix\Main\Test\Typography\AuthorTable::query() ->addSelect('ID') ->addSelect('FULL_NAME') ->where('ID', 17) - ->fetchObject(); + ->fetchObject() +; echo $author['FULL_NAME']; // Аналогично вызову метода $author->get('FULL_NAME') diff --git a/pages/orm/orm-concepts.md b/pages/orm/orm-concepts.md index b49ac3d..66e8be5 100644 --- a/pages/orm/orm-concepts.md +++ b/pages/orm/orm-concepts.md @@ -17,10 +17,10 @@ ORM (Object-Relational Mapping) — это технология, которая ```sql Book - ID int [autoincrement, primary] - ISBN str [match: /[0-9X-]+/] - TITLE str [max_length: 50] - PUBLISH_DATE date + ID int [autoincrement, primary] + ISBN str [match: /[0-9X-]+/] + TITLE str [max_length: 50] + PUBLISH_DATE date ``` Здесь: @@ -421,14 +421,12 @@ new Entity\ExpressionField('AGE_DAYS', ```php class BookTable extends Entity\DataManager { - ... - - public static function getUfId() - { - return 'MY_BOOK'; - } - - ... + public static function getUfId() + { + return 'MY_BOOK'; + } + + // ... } ``` @@ -570,7 +568,9 @@ new Entity\StringField('ISBN', [ if (preg_match('/^\d{13}$/', $clean)) { // Проверяем, что значение состоит из 13 цифр return true; // Если условие выполняется, валидация успешна - } else { + } + else + { return 'Код ISBN должен содержать 13 цифр.'; // Сообщение об ошибке, если условие не выполняется } } @@ -619,7 +619,9 @@ new Entity\StringField('ISBN', [ $clean = str_replace('-', '', $value); // Удаляем дефисы из значения if (preg_match('/^\d{13}$/', $clean)) { // Проверяем, что значение состоит из 13 цифр return true; // Если условие выполняется, валидация успешна - } else { + } + else + { return 'Код ISBN должен содержать 13 цифр.'; // Сообщение об ошибке, если условие не выполняется } }, @@ -638,12 +640,15 @@ new Entity\StringField('ISBN', [ ```php // выполняем операцию $result = BookTable::update(...); -if (!$result->isSuccess()) { +if (!$result->isSuccess()) +{ // Получаем список ошибок $errors = $result->getErrors(); - foreach ($errors as $error) { - if ($error->getCode() == 'MY_ISBN_CHECKSUM') { + foreach ($errors as $error) + { + if ($error->getCode() == 'MY_ISBN_CHECKSUM') + { // Обработка ошибки, связанной с нашим валидатором контрольной цифры ISBN } } diff --git a/pages/orm/query-builder.md b/pages/orm/query-builder.md index 1e5a7d4..fded6d2 100644 --- a/pages/orm/query-builder.md +++ b/pages/orm/query-builder.md @@ -45,7 +45,8 @@ function attachSelect(Entity\Query $query): void $query->addSelect('ID'); // Условие для добавления поля ISBN - if (/* условие */) { + if (/* условие */) + { $query->addSelect('ISBN'); } } @@ -53,12 +54,14 @@ function attachSelect(Entity\Query $query): void function attachOthers(Entity\Query $query): void { // Условие для добавления фильтра - if (/* условие */) { + if (/* условие */) + { $query->setFilter(/* параметры фильтра */); } // Условие для добавления сортировки - if (/* условие */) { + if (/* условие */) + { $query->setOrder(/* параметры сортировки */); } } diff --git a/pages/orm/querying-data.md b/pages/orm/querying-data.md index 605b280..06ceba1 100644 --- a/pages/orm/querying-data.md +++ b/pages/orm/querying-data.md @@ -12,7 +12,7 @@ description: 'Выборка данных. ORM Bitrix Framework: ключевы Рассмотрим применение метода на примере сущности `BookTable`. Метод принимает параметры: ```php -use \Bitrix\Main\ORM; +use Bitrix\Main\ORM; $result = BookTable::getList([ 'select' => ['ISBN', 'TITLE', 'PUBLISH_DATE', 'CNT'], // поля, которые нужно получить @@ -24,7 +24,7 @@ $result = BookTable::getList([ 'runtime' => [ // динамически определенные поля new ORM\Fields\ExpressionField('CNT', 'COUNT(*)') ], - 'count_total' => true // список всех элементов без постраничного вывода + 'count_total' => true // список всех элементов без постраничного вывода ]); ``` @@ -51,7 +51,7 @@ $result = BookTable::getList([ // Получение данных построчно $rows = []; $result = BookTable::getList($parameters); -while ($row = $result->fetch()) +while ($row = $result->fetch()) { $rows[] = $row; } @@ -71,9 +71,9 @@ class BookTable extends \Bitrix\Main\Entity\DataManager { return [ function ($data) - { - if (isset($data['PUBLISH_DATE'])) - { + { + if (isset($data['PUBLISH_DATE'])) + { $data['PUBLISH_DATE'] = date('d.m.Y', strtotime($data['PUBLISH_DATE'])); } return $data; @@ -298,7 +298,7 @@ BookTable::getList([ Для подсчета количества записей используйте `ExpressionField`: ```php -use \Bitrix\Main\ORM; +use Bitrix\Main\ORM; BookTable::getList([ 'select' => ['CNT'], @@ -316,7 +316,7 @@ BookTable::getList([ После того, как добавили вычисляемое поле, его можно использовать в фильтрах: ```php -use \Bitrix\Main\ORM; +use Bitrix\Main\ORM; BookTable::getList([ 'select' => ['PUBLISH_DATE'], @@ -341,7 +341,7 @@ BookTable::getList([ Если вычисляемое поле нужно только в `select`, `runtime` можно не использовать. Система поддерживает вложенные выражения, которые разворачиваются в финальном SQL. ```php -use \Bitrix\Main\ORM; +use Bitrix\Main\ORM; BookTable::getList([ 'select' => [ @@ -492,7 +492,7 @@ $row = $result->fetch(); Одну таблицу можно описать несколькими сущностями, разделив записи на сегменты. Метод `setDefaultScope` выполняется при каждом запросе, задавая фильтры и другие параметры. ```php -use \Bitrix\Main\ORM\Query\Query; +use Bitrix\Main\ORM\Query\Query; class Element4Table extends \Bitrix\Iblock\ElementTable { @@ -534,7 +534,7 @@ class Element5Table extends \Bitrix\Iblock\ElementTable На пользовательском уровне можно задавать предустановленные выборки с помощью методов `with*`, аналога `setDefaultScope`. ```php -use \Bitrix\Main\ORM\Query\Query; +use Bitrix\Main\ORM\Query\Query; class UserTable { @@ -548,7 +548,8 @@ class UserTable // Использование метода withActive $activeUsers = UserTable::query() ->withActive() // Применяем фильтр для активных пользователей - ->fetchCollection(); // Выполняем запрос и получаем коллекцию + ->fetchCollection() // Выполняем запрос и получаем коллекцию +; // WHERE `ACTIVE`='Y' ``` @@ -559,7 +560,7 @@ $activeUsers = UserTable::query() Метод принимает объект `Bitrix\Main\ORM\Query\Query`, позволяя задавать фильтры и другие параметры. Можно добавить свои аргументы: ```php -use \Bitrix\Main\ORM\Query\Query; +use Bitrix\Main\ORM\Query\Query; class UserTable { @@ -568,14 +569,16 @@ class UserTable { $query ->addSelect('LOGIN') // Добавляем поле LOGIN в выборку - ->where('ACTIVE', $value); // Фильтр ACTIVE = $value + ->where('ACTIVE', $value) // Фильтр ACTIVE = $value + ; } } // Использование метода withActive $activeUsers = UserTable::query() ->withActive(false) // Применяем фильтр для неактивных пользователей - ->fetchCollection(); // Выполняем запрос и получаем коллекцию + ->fetchCollection() // Выполняем запрос и получаем коллекцию +; // SELECT `LOGIN` ... WHERE `ACTIVE`='N' ``` @@ -621,9 +624,12 @@ public static function getTableName() { public function quote($identifier) { - if (self::isKnownFunctionCall($identifier)) { + if (self::isKnownFunctionCall($identifier)) + { return $identifier; - } else { + } + else + { return parent::quote($identifier); } } @@ -650,7 +656,8 @@ public static function getTableName() $query = BookTable::query() ->addSelect('NAME') ->addSelect('AUTHORS') - ->setLimit(5); + ->setLimit(5) +; $books = $query->fetchCollection(); // SQL-запрос: @@ -670,7 +677,8 @@ $query = BookTable::query() ->addSelect('NAME') ->addSelect('AUTHORS') ->addSelect('CATEGORIES') - ->addSelect('TAGS'); + ->addSelect('TAGS') +; $books = $query->fetchCollection(); // SQL-запрос @@ -723,7 +731,8 @@ public static function decompose(Query $query, $fairLimit = true, $separateRelat ```php \Bitrix\Main\UserTable::query() ->where("ID", 1) - ->exec(); + ->exec() + ; // WHERE `main_user`.`ID` = 1 ``` @@ -734,7 +743,8 @@ public static function decompose(Query $query, $fairLimit = true, $separateRelat ```php \Bitrix\Main\UserTable::query() ->where("ID", "<", 10) - ->exec(); + ->exec() + ; // WHERE `main_user`.`ID` < 10 ``` @@ -757,7 +767,8 @@ public static function decompose(Query $query, $fairLimit = true, $separateRelat ```php \Bitrix\Main\UserTable::query() ->whereNull("ID") - ->exec(); + ->exec() + ; // WHERE `main_user`.`ID` IS NULL ``` @@ -770,7 +781,8 @@ public static function decompose(Query $query, $fairLimit = true, $separateRelat ```php \Bitrix\Main\UserTable::query() ->whereNotNull("ID") - ->exec(); + ->exec() + ; // WHERE `main_user`.`ID` IS NOT NULL ``` @@ -781,7 +793,8 @@ public static function decompose(Query $query, $fairLimit = true, $separateRelat ```php \Bitrix\Main\UserTable::query() ->whereExpr('JSON_CONTAINS(%s, 4)', ['SOME_JSON_FIELD']) - ->exec(); + ->exec() + ; // WHERE JSON_CONTAINS(`main_user`.`SOME_JSON_FIELD`, 4) ``` @@ -794,7 +807,8 @@ public static function decompose(Query $query, $fairLimit = true, $separateRelat ```php \Bitrix\Main\UserTable::query() ->whereColumn('NAME', 'LOGIN') - ->exec(); + ->exec() + ; // WHERE `main_user`.`NAME` = `main_user`.`LOGIN` ``` @@ -803,7 +817,8 @@ public static function decompose(Query $query, $fairLimit = true, $separateRelat ```php \Bitrix\Main\UserTable::query() ->where('NAME', new Query\Filter\Expression\Column('LOGIN')) - ->exec(); + ->exec() + ; // WHERE `main_user`.`NAME` = `main_user`.`LOGIN` ``` @@ -815,7 +830,8 @@ public static function decompose(Query $query, $fairLimit = true, $separateRelat new Column('NAME'), new Column('LAST_NAME') ]) - ->exec(); + ->exec() + ; // WHERE `main_user`.`LOGIN` IN (`main_user`.`NAME`, `main_user`.`LAST_NAME`) ``` @@ -831,7 +847,8 @@ public static function decompose(Query $query, $fairLimit = true, $separateRelat ->where('ACTIVE', true) ->whereNotNull('PERSONAL_BIRTHDAY') ->whereLike('NAME', 'A%') - ->exec(); + ->exec() +; // WHERE `main_user`.`ID` > 1 AND `main_user`.`ACTIVE` = 'Y' AND `main_user`.`PERSONAL_BIRTHDAY` IS NOT NULL AND `main_user`.`NAME` LIKE 'A%' ``` @@ -851,7 +868,8 @@ public static function decompose(Query $query, $fairLimit = true, $separateRelat ['PERSONAL_BIRTHDAY', '<>', null], ['NAME', 'like', 'A%'] ]) - ->exec(); + ->exec() +; // WHERE `main_user`.`ID` > 1 AND `main_user`.`ACTIVE` = 'Y' AND `main_user`.`PERSONAL_BIRTHDAY` IS NOT NULL AND `main_user`.`NAME` LIKE 'A%' ``` @@ -867,7 +885,8 @@ public static function decompose(Query $query, $fairLimit = true, $separateRelat ['ID', '>', 1], ['ACTIVE', true] ]) - ->exec(); + ->exec() +; // WHERE `main_user`.`ID` > 1 AND `main_user`.`ACTIVE` = 'Y' ``` @@ -875,12 +894,14 @@ public static function decompose(Query $query, $fairLimit = true, $separateRelat Вы можете использовать вложенные фильтры для более сложных условий: ```php -use \Bitrix\Main\ORM\Query\Query; +use Bitrix\Main\ORM\Query\Query; + \Bitrix\Main\UserTable::query() ->where(Query::filter()->where([ ["ID", '>', 1], ['ACTIVE', true] - ]))->exec(); + ]))->exec() +; // WHERE `main_user`.`ID` > 1 AND `main_user`.`ACTIVE` = 'Y' ``` @@ -888,7 +909,8 @@ use \Bitrix\Main\ORM\Query\Query; Для объединения условий с логикой `OR`: ```php -use \Bitrix\Main\ORM\Query\Query; +use Bitrix\Main\ORM\Query\Query; + \Bitrix\Main\UserTable::query() ->where('ACTIVE', true) ->where(Query::filter() @@ -897,7 +919,8 @@ use \Bitrix\Main\ORM\Query\Query; ['ID', 1], ['LOGIN', 'admin'] ]) - )->exec(); + )->exec() +; // WHERE `main_user`.`ACTIVE` = 'Y' AND (`main_user`.`ID` = 1 OR `main_user`.`LOGIN` = 'admin') ``` @@ -905,7 +928,8 @@ use \Bitrix\Main\ORM\Query\Query; Вы также можете использовать цепочку вызовов для создания условий с `OR`: ```php -use \Bitrix\Main\ORM\Query\Query; +use Bitrix\Main\ORM\Query\Query; + \Bitrix\Main\UserTable::query() ->where('ACTIVE', true) ->where(Query::filter() @@ -913,7 +937,8 @@ use \Bitrix\Main\ORM\Query\Query; ->where('ID', 1) ->where('LOGIN', 'admin') ) - ->exec(); + ->exec() +; // WHERE `main_user`.`ACTIVE` = 'Y' AND (`main_user`.`ID` = 1 OR `main_user`.`LOGIN` = 'admin') ``` @@ -922,26 +947,29 @@ use \Bitrix\Main\ORM\Query\Query; В фильтре можно использовать `ExpressionField`, который автоматически регистрируется как runtime поле. Это позволяет создавать сложные условия: ```php -use \Bitrix\Main\ORM\Fields\ExpressionField; +use Bitrix\Main\ORM\Fields\ExpressionField; \Bitrix\Main\UserTable::query() ->where(new ExpressionField('LNG', 'LENGTH(%s)', 'LAST_NAME'), '>', 10) - ->exec(); + ->exec() +; // WHERE LENGTH(`main_user`.`LAST_NAME`) > '10' ``` Для упрощения таких конструкций используйте хелпер. Хелпер — это вспомогательный метод, который упрощает работу с выражениями. `Query::expr()` является хелпером, который позволяет использовать SQL-функции: ```php -use \Bitrix\Main\ORM\Query\Query; +use Bitrix\Main\ORM\Query\Query; \Bitrix\Main\UserTable::query() ->where(Query::expr()->length("LAST_NAME"), '>', 10) - ->exec(); + ->exec() +; // WHERE LENGTH(`main_user`.`LAST_NAME`) > '10' \Bitrix\Main\UserTable::query() ->addSelect(Query::expr()->count("ID"), 'CNT') - ->exec(); + ->exec() +; // SELECT COUNT(`main_user`.`ID`) AS `CNT` FROM `b_user` `main_user` ``` @@ -972,7 +1000,7 @@ use \Bitrix\Main\ORM\Query\Query; При использовании `getList`, фильтр можно вставить вместо массива: ```php -use \Bitrix\Main\ORM\Query\Query; +use Bitrix\Main\ORM\Query\Query; \Bitrix\Main\UserTable::getList([ 'filter' => ['=ID' => 1] ]); @@ -989,8 +1017,8 @@ use \Bitrix\Main\ORM\Query\Query; Референсы — это связи между таблицами, которые позволяют объединять данные из разных таблиц. Они описываются с помощью `ReferenceField`: ```php -use \Bitrix\Main\Entity; -use \Bitrix\Main\ORM\Query\Join; +use Bitrix\Main\Entity; +use Bitrix\Main\ORM\Query\Join; new Entity\ReferenceField('GROUP', GroupTable::class, Join::on('this.GROUP_ID', 'ref.ID') @@ -1000,8 +1028,8 @@ new Entity\ReferenceField('GROUP', GroupTable::class, Метод `on` — это сокращенная запись `Query::filter()` с предустановленным условием по колонкам. Он позволяет строить условия JOIN: ```php -use \Bitrix\Main\Entity; -use \Bitrix\Main\ORM\Query\Join; +use Bitrix\Main\Entity; +use Bitrix\Main\ORM\Query\Join; new Entity\ReferenceField('GROUP', GroupTable::class, Join::on('this.GROUP_ID', 'ref.ID') @@ -1017,7 +1045,8 @@ new Entity\ReferenceField('GROUP', GroupTable::class, Везде, где указывается имя поля, можно указать любую цепочку переходов: ```php -->whereColumn('this.AUTHOR.UserGroup:USER.GROUP.OWNER.ID', 'ref.ID'); +->whereColumn('this.AUTHOR.UserGroup:USER.GROUP.OWNER.ID', 'ref.ID') +; ``` ### Формат массива diff --git a/pages/performance/caching.md b/pages/performance/caching.md index e7dbc89..bd700d5 100644 --- a/pages/performance/caching.md +++ b/pages/performance/caching.md @@ -82,7 +82,7 @@ if ($cache->initCache( } elseif ($cache->startDataCache()) { - $result = array(); + $result = []; // Если данные недействительны, отменяем кеширование if ($isInvalid) { diff --git a/pages/performance/composite-site.md b/pages/performance/composite-site.md index e44244d..fe6e5d9 100644 --- a/pages/performance/composite-site.md +++ b/pages/performance/composite-site.md @@ -737,7 +737,7 @@ BX.addCustomEvent("onFrameDataRequestFail", function(response) { - `AssetMode::NO_ASSETS` — ресурсы не добавляются в ``. -```javascript +```php $dynamicArea = new \Bitrix\Main\Page\FrameStatic("workarea"); $dynamicArea->setAssetMode(AssetMode::STANDARD); // Устанавливает режим добавления ресурсов @@ -822,7 +822,7 @@ $id = $this->randString(); // Генерация стабильного иден Для хранения данных в локальном хранилище браузера используйте метод `setBrowserStorage(true)`. -```javascript +```php $frame = $this->createFrame()->begin(); // Создание динамической зоны $frame->setBrowserStorage(true); // Включает использование локального хранилища браузера // Здесь размещается динамический контент @@ -833,7 +833,7 @@ $frame->end(); // Завершение динамической зоны Если нужно кешировать весь контент шаблона и обновлять его на втором хите, поместите код шаблона в `createFrame()->begin()`. -```javascript +```php $frame = $this->createFrame()->begin(); // Начало динамической зоны для всего шаблона // Весь контент шаблона $frame->end(); // Завершение динамической зоны diff --git a/pages/performance/hot-and-cold-session.md b/pages/performance/hot-and-cold-session.md index 5ca4a61..7f65b8b 100644 --- a/pages/performance/hot-and-cold-session.md +++ b/pages/performance/hot-and-cold-session.md @@ -43,7 +43,7 @@ description: 'Сессия в разделенном режиме. Оптими ```php return [ - //... + // ... 'session' => [ 'value' => [ 'mode' => 'separated', diff --git a/pages/performance/query-optimization.md b/pages/performance/query-optimization.md index 3a79318..0840645 100644 --- a/pages/performance/query-optimization.md +++ b/pages/performance/query-optimization.md @@ -14,8 +14,10 @@ description: 'Как оптимизировать запросы к базе д - Неправильный подход: выполнить запрос в цикле. Для каждого товара в корзине выполняется отдельный запрос к базе данных. Это неэффективно, так как количество запросов растет с увеличением числа товаров. ```php - foreach ($arResult["ORDERS"] as $key => $val) { - foreach ($val["BASKET_ITEMS"] as $vvval) { + foreach ($arResult["ORDERS"] as $key => $val) + { + foreach ($val["BASKET_ITEMS"] as $vvval) + { $rsEls = CIBlockElement::GetByID($vvval["PRODUCT_ID"]); // Запрос в цикле } } @@ -28,15 +30,18 @@ description: 'Как оптимизировать запросы к базе д $arIDs = array(); // Перебираем заказы и товары в корзине - foreach($arResult["ORDERS"] as $key => $val) { - foreach($val["BASKET_ITEMS"] as $vvval) { + foreach($arResult["ORDERS"] as $key => $val) + { + foreach($val["BASKET_ITEMS"] as $vvval) + { // Добавляем ID товара в массив $arIDs[] = $vvval["PRODUCT_ID"]; } } // Если массив не пустой, выполняем один запрос - if (!empty($arIDs)) { + if (!empty($arIDs)) + { $rsEls = CIBlockElement::GetList( [], ["ID" => $arIDs], @@ -46,8 +51,10 @@ description: 'Как оптимизировать запросы к базе д ); // Наполняем данные, используя ID - foreach($arResult["ORDERS"] as $key => $val) { - foreach($val["BASKET_ITEMS"] as $vvval) { + foreach($arResult["ORDERS"] as $key => $val) + { + foreach($val["BASKET_ITEMS"] as $vvval) + { // Работа с данными } } @@ -102,7 +109,8 @@ $rs = CIBlockElement::GetList( ); // Сохраняем результаты -while($ar = $rs->GetNext()) { +while($ar = $rs->GetNext()) +{ $arResult['ITEMS'][] = $ar; } ``` @@ -129,7 +137,8 @@ while($ar = $rs->GetNext()) { ```php Bitrix\Iblock\ElementTable::query() ->setSelect(['ID', 'NAME', 'CODE']) - ->where('CODE','xxx')->exec(); + ->where('CODE','xxx')->exec() + ; ``` Здесь фильтр `where('CODE', 'xxx')` отбирает элементы, у которых поле `CODE` равно `'xxx'`. diff --git a/pages/security/access-control.md b/pages/security/access-control.md index f0ac7e2..c04769f 100644 --- a/pages/security/access-control.md +++ b/pages/security/access-control.md @@ -196,7 +196,7 @@ $PERM["файл_или_папка"]["ID_группы"] = "уровень_дос ### Пример настройки прав через файл ```php -SetCodeCrypt($captchaPass); Добавьте в форму три элемента: -```html +```php - + - + ``` Чтобы проверить, правильно ли пользователь ввел CAPTCHA, добавьте в обработчик формы код: @@ -123,10 +124,13 @@ $cpt->SetCodeCrypt($captchaPass); ```php CaptchaCheckCode($_POST["captcha_word"], $_POST["captcha_code"])) { +if (!$APPLICATION->CaptchaCheckCode($_POST["captcha_word"], $_POST["captcha_code"])) +{ // Неправильное значение echo "CAPTCHA введена неверно. Попробуйте еще раз."; -} else { +} +else +{ // Правильное значение echo "CAPTCHA введена верно."; } @@ -148,12 +152,12 @@ $code = $APPLICATION->CaptchaGetCode(); Код передается в HTML для отображения картинки. Картинка генерируется скриптом `/bitrix/tools/captcha.php`. -```html +```php - + -CAPTCHA +CAPTCHA ``` При обращении к скрипту: @@ -166,7 +170,8 @@ $code = $APPLICATION->CaptchaGetCode(); ```php // Проверяем введенный пользователем код CAPTCHA -if (!$APPLICATION->CaptchaCheckCode($_POST["captcha_word"], $_POST["captcha_sid"])) { +if (!$APPLICATION->CaptchaCheckCode($_POST["captcha_word"], $_POST["captcha_sid"])) +{ echo 'Неверный код CAPTCHA'; } ``` @@ -202,10 +207,10 @@ $code = $cpt->GetSID(); 3. Обновите путь к файлу в HTML-коде. -```html +```php - + -CAPTCHA +CAPTCHA ``` diff --git a/pages/security/cryptofield.md b/pages/security/cryptofield.md index 18f742b..af7b846 100644 --- a/pages/security/cryptofield.md +++ b/pages/security/cryptofield.md @@ -257,9 +257,9 @@ use Bitrix\Main\ORM\Fields\SecretField; public static function getMap() { return [ - // ... + // ... // другие поля - // ... + // ... 'API_TOKEN' => new SecretField('API_TOKEN', [ 'secret_length' => 32, diff --git a/pages/security/csrf-ssrf.md b/pages/security/csrf-ssrf.md index 9e5edb7..ec8f408 100644 --- a/pages/security/csrf-ssrf.md +++ b/pages/security/csrf-ssrf.md @@ -71,7 +71,8 @@ Bitrix Framework предоставляет функции для работы В общем виде для проверки корректности запроса достаточно добавить `check_bitrix_sessid` в условие: ```php -if (check_bitrix_sessid()) { +if (check_bitrix_sessid()) +{ // Действие выполняется } ``` @@ -88,10 +89,10 @@ HTML-инъекции могут нарушить форматирование ```php
- - - ... + + + ...
``` @@ -116,8 +117,8 @@ HTML-инъекции могут нарушить форматирование ```php
- - ... + + ...
``` @@ -199,11 +200,15 @@ $http->get($_GET['uri']); // Пытаемся отправить запрос ```php $file = CFile::MakeFileArray($_GET['uri']); -if ($file) { +if ($file) +{ $res = CFile::CheckImageFile($file); - if ($res === null) { + if ($res === null) + { // Изображение корректно, можно продолжать - } else { + } + else + { // Обработка ошибки } } diff --git a/pages/security/jwt.md b/pages/security/jwt.md index 4dc1c3b..fab4b53 100644 --- a/pages/security/jwt.md +++ b/pages/security/jwt.md @@ -96,11 +96,14 @@ use Bitrix\Main\Web\JWT; $secret = 'ваш-секретный-ключ'; $jwt = 'токен-полученный-от-клиента'; -try { +try +{ $payload = JWT::decode($jwt, $secret, ['HS256']); // Токен верный, работаем с данными: echo 'Пользователь: ' . $payload->name; -} catch (Exception $e) { +} +catch (Exception $e) +{ // Токен не прошёл проверку echo 'Ошибка: ' . $e->getMessage(); } diff --git a/pages/security/secure-cookies.md b/pages/security/secure-cookies.md index 25fc6ae..3aa94c7 100644 --- a/pages/security/secure-cookies.md +++ b/pages/security/secure-cookies.md @@ -20,14 +20,14 @@ description: 'Защищенные cookie. Руководство по безо ```php [ 'value' => [ 'crypto_key' => 'mysupersecretphrase', ], 'readonly' => true, // 'readonly' указывает, что значение 'crypto_key' нельзя изменить через интерфейс администратора. Это повышает безопасность: ключ остается постоянным и защищенным от случайных изменений ] - //... + // ... ]; ``` diff --git a/pages/security/sql-injection.md b/pages/security/sql-injection.md index 999a706..d102e6c 100644 --- a/pages/security/sql-injection.md +++ b/pages/security/sql-injection.md @@ -114,7 +114,7 @@ $select = $_REQUEST['select'] //['ID' => 'ID', 'TITLE' => 'TITLE', 'LAST_NAME' => 'RESPONSIBLE.LAST_NAME']; $result = \Bitrix\Tasks\Internals\TaskTable::getList([ - 'select' => $select // доступ к любым поля и связям + 'select' => $select // доступ к любым поля и связям ]); var_dump($result->fetchAll()); @@ -140,7 +140,7 @@ var_dump($result->fetchAll()); // Пример подбора email через фильтр $result = \Bitrix\Main\UserTable::getList([ // Если что-то возвращается, значит email начинается с буквы А. Если нет — пробуем другой символ. - 'filter' => ['ID' => 1, '%=EMAIL' => "A%"] + 'filter' => ['ID' => 1, '%=EMAIL' => "A%"] ]); ``` diff --git a/pages/security/xss.md b/pages/security/xss.md index f610696..fb56b5d 100644 --- a/pages/security/xss.md +++ b/pages/security/xss.md @@ -21,7 +21,7 @@ XSS (Cross-Site Scripting) — уязвимость, которая позвол {% endnote %} -```html +```php
@@ -53,7 +53,7 @@ const valueEscaped = Text.encode(valueNotSafe); Заключайте значения атрибутов в двойные кавычки `"`. С одинарными кавычками экранирование не сработает. -```html +```php @@ -65,7 +65,7 @@ const valueEscaped = Text.encode(valueNotSafe); Метод `CUtil::JSEscape` экранирует спецсимволы JavaScript `'`, `"`, `\`, `\n`, `\r`. Подходит для строк, заключенных в кавычки. -```html +```php // Правильно: строка в кавычках, спецсимволы экранированы ``` diff --git a/pages/ui/dialogs-messagebox.md b/pages/ui/dialogs-messagebox.md index bc2f1eb..9bc2be7 100644 --- a/pages/ui/dialogs-messagebox.md +++ b/pages/ui/dialogs-messagebox.md @@ -65,10 +65,10 @@ MessageBox.alert(message, title, onOk, okCaption); import { MessageBox } from 'ui.dialogs.messagebox'; MessageBox.alert( - 'Проверьте параметры перед продолжением.', - 'Параметры задачи', - () => true, - 'Понятно', + 'Проверьте параметры перед продолжением.', + 'Параметры задачи', + () => true, + 'Понятно', ); ``` @@ -86,15 +86,15 @@ MessageBox.alert( import { MessageBox } from 'ui.dialogs.messagebox'; MessageBox.confirm( - 'Удалить элемент?', - (messageBox) => { - return BX.ajax.runAction('example.Item.delete', { - data: { - id: 42, - }, - }); - }, - 'Удалить', + 'Удалить элемент?', + (messageBox) => { + return BX.ajax.runAction('example.Item.delete', { + data: { + id: 42, + }, + }); + }, + 'Удалить', ); ``` @@ -132,13 +132,13 @@ MessageBox.confirm(message, title, onOk, okCaption, onCancel, cancelCaption, use import { MessageBox } from 'ui.dialogs.messagebox'; MessageBox.confirm( - 'Отменить изменения в форме?', - 'Несохраненные данные', - () => true, - 'Отменить изменения', - () => false, - 'Вернуться', - true, + 'Отменить изменения в форме?', + 'Несохраненные данные', + () => true, + 'Отменить изменения', + () => false, + 'Вернуться', + true, ); ``` @@ -152,10 +152,10 @@ MessageBox.confirm( import { MessageBox } from 'ui.dialogs.messagebox'; MessageBox.show({ - title: 'Заявка отправлена', - message: 'Ответственный получит уведомление.', - modal: true, - buttons: BX.UI.Dialogs.MessageBoxButtons.OK, + title: 'Заявка отправлена', + message: 'Ответственный получит уведомление.', + modal: true, + buttons: BX.UI.Dialogs.MessageBoxButtons.OK, }); ``` @@ -169,15 +169,15 @@ MessageBox.show({ import { MessageBox } from 'ui.dialogs.messagebox'; const messageBox = new MessageBox({ - title: 'Удалить контакт', - message: 'Контакт будет удален из адресной книги.', - buttons: BX.UI.Dialogs.MessageBoxButtons.OK_CANCEL, - okCaption: 'Удалить', - cancelCaption: 'Отмена', - onOk: () => { - messageBox.close(); - return false; - }, + title: 'Удалить контакт', + message: 'Контакт будет удален из адресной книги.', + buttons: BX.UI.Dialogs.MessageBoxButtons.OK_CANCEL, + okCaption: 'Удалить', + cancelCaption: 'Отмена', + onOk: () => { + messageBox.close(); + return false; + }, }); messageBox.show(); @@ -243,16 +243,16 @@ messageBox.show(); import { MessageBox } from 'ui.dialogs.messagebox'; const messageBox = new MessageBox({ - message: 'Выберите действие.', - buttons: [ - new BX.UI.Button({ - text: 'Архивировать', - color: BX.UI.Button.Color.PRIMARY, - events: { - click: () => messageBox.close(), - }, - }), - ], + message: 'Выберите действие.', + buttons: [ + new BX.UI.Button({ + text: 'Архивировать', + color: BX.UI.Button.Color.PRIMARY, + events: { + click: () => messageBox.close(), + }, + }), + ], }); messageBox.show(); @@ -280,16 +280,16 @@ messageBox.show(); import { MessageBox } from 'ui.dialogs.messagebox'; const messageBox = new MessageBox({ - message: 'Удалить элемент?', - buttons: BX.UI.Dialogs.MessageBoxButtons.OK_CANCEL, - onOk: (box, button, event) => { - return BX.ajax.runAction('example.Item.delete', { - data: { - id: 42, - }, - }); - }, - onCancel: () => true, + message: 'Удалить элемент?', + buttons: BX.UI.Dialogs.MessageBoxButtons.OK_CANCEL, + onOk: (box, button, event) => { + return BX.ajax.runAction('example.Item.delete', { + data: { + id: 42, + }, + }); + }, + onCancel: () => true, }); messageBox.show(); @@ -317,8 +317,8 @@ messageBox.show(); import { MessageBox } from 'ui.dialogs.messagebox'; const messageBox = new MessageBox({ - message: 'Идет проверка данных.', - buttons: BX.UI.Dialogs.MessageBoxButtons.OK, + message: 'Идет проверка данных.', + buttons: BX.UI.Dialogs.MessageBoxButtons.OK, }); messageBox.show(); diff --git a/pages/ui/hint.md b/pages/ui/hint.md index 77b024d..fa6a575 100644 --- a/pages/ui/hint.md +++ b/pages/ui/hint.md @@ -76,8 +76,8 @@ import { Dom, Tag } from 'main.core'; const container = document.getElementById('settings-container'); Dom.append( - Tag.render``, - container, + Tag.render``, + container, ); BX.UI.Hint.init(container);