Bitrix system field edit

Разбираем на примерах как получать поля и свойства элементов инфоблоков в Битрикс D7

Пользовательские поля

Хотя Битрикс предлагает большой набор предопределенных полей, их все-таки может не хватить. Тогда остается только создавать свои поля. Это можно сделать в панели управления: «Настройки • Настройки продукта • Пользовательские поля»:

4.jpg

Я добавил поле «Мое поле», тип «Строка», в настройках компонента указал, что это поле надо показывать:

5.jpg

Теперь форма регистрации имеет вид:

6.jpg

Примеры работы

Рассмотрим несколько примеров работы с пользовательскими полями

Фильтрация Сортировка Получение значений Использование пользовательских свойств на примере дополнительных полей в подписке

Пользовательские поля разделов могут принимать участие в фильтрации.

$sec_Filter= array( “IBLOCK_ID” => $IBLOCK_ID, “DEPTH_LEVEL” => “2”, “!UF_ARC_PAGES” => “”);

Примечание: Фильтрация по пользовательским полям работает только при наличии фильтра по IBLOCK_ID.

Будут отобраны все разделы, у которых установлено значение свойства UF_ARC_PAGES.

Фильтрация по значению пользовательского свойства:

$arSFilter [‘=UF_USERS_PROPERTY’] =$users_property_value;

Сортировать по пользовательским полям разделов:

$arSort = array( “UF_RATING”=>”asc”, “sort”=>”asc” );

Получить значение пользовательского поля можно с помощью метода GetList соответствующего класса.

Значение пользовательского поля для пользователя можно получить таким образом:

$rsUser = CUser::GetByID($user);$arUser = $rsUser->Fetch();$нужное значение = $arUser[‘код пользовательского поля’];

Чтобы получить значение пользовательского поля определенного пользователя, тип поля – строка, необходимо воспользоваться методом GetList класса CUser. При этом в качестве четвертого аргумента данному методу необходимо передать массив с ключом SELECT, значениями которого являются список кодов пользовательских свойств, которые необходимо получить.

global $USER;$arFilter = array(“ID” => $USER->GetID());$arParams[“SELECT”] = array(“UF_USER_CARD_CODE”);$arRes = CUser::GetList($by,$desc,$arFilter,$arParams); if ($res = $arRes->Fetch()) { echo $res[“UF_USER_CARD_CODE”]; }

Если тип пользовательского поля список, то для получения значения (или значений, если возможен множественный выбор) текущего пользователя нужно воспользоваться методом GetList класса CUserFieldEnum.

global $USER;$arFilter = array(“ID” => $USER->GetID());$arParams[“SELECT”] = array(“UF_LIST_TASK”);$arRes = CUser::GetList($by,$desc,$arFilter,$arParams); if ($res = $arRes->Fetch()) { foreach ($res[“UF_LIST_TASK “] as $id) { $rsRes= CUserFieldEnum::GetList(array(), array( “ID” => $id, )); if($arGender = $rsRes->GetNext()) echo $arGender[“VALUE”]; } }

Если необходимо получить список всех значений пользовательского поля объекта USER типа список, то следует воспользоваться следующим кодом:

global $USER_FIELD_MANAGER;$arFields = $USER_FIELD_MANAGER->GetUserFields(“USER”);$obEnum = new CUserFieldEnum;$rsEnum = $obEnum->GetList(array(), array(“USER_FIELD_ID” => $arFields[“UF_LIST_TASK “][“ID”]));while($arEnum = $rsEnum->GetNext()){ echo $arEnum[“VALUE”];}

Для выбора значения пользовательского поля у раздела информационного блока можно воспользоваться методом CIBlockSection:GetList:

$aSection = CIBlockSection::GetList( array(), array( ‘IBLOCK_ID’ => 3, ‘CODE’ => ‘test_section’,), false, array( ‘UF_DEV2DAY_FIELD’ ) )->Fetch();

Примечание: Передача идентификатора инфоблока (IBLOCK_ID) обязательна, иначе выборка пользовательских свойств не будет осуществлена.

Получение значения пользовательского поля типа файл конкретного раздела инфоблока:

$iblockID = 1; $sectionID = 10; // ID секции $propertyCode = ‘UF_MY_FILE’; // Код свойства $rsResult = CIBlockSection::GetList(array(“SORT” => “ASC”), array(“ID” => $sectionID, “IBLOCK_ID” => $iblockID), false, $arSelect = array(“ID”, “IBLOCK_ID”, $propertyCode)); if ($arResult = $rsResult -> GetNext()) { echo ”, mydump($arResult), ”; }

Так как пользовательские поля можно использовать не только с разделами информационного блока, но и с любыми другими сущностями, то для выбора значений по идентификатору сущности используется класс CUserTypeManager. Экземпляр данного класса уже находится в глобальной переменной $USER_FIELD_MANAGER.

global $USER_FIELD_MANAGER; $aSection = CIBlockSection::GetList( array(), array( ‘IBLOCK_CODE’ => ‘shop_news’, ‘CODE’ => ‘test_section’,) )->Fetch(); if( !$aSection ) { throw new Exception( ‘Секция не найдена’ );} $aUserField = $USER_FIELD_MANAGER->GetUserFields(‘IBLOCK_3_SECTION’,$aSection[‘ID’]); // array

В результате мы получим массив содержащий в себе всю информацию о поле и его значении для конкретного объекта.

Примечание: Чтобы получить все значения пользовательских полей в параметре arSelect достаточно указать Array(“UF_*”).

Использование пользовательских свойств на примере дополнительных полей в подписке

Задача: подписчиком будет указываться пол, и в зависимости от этого выбора в письме рассылки она или он получит “Уважаемая” или “Уважаемый” в качестве обращения.

В решении используется демо дистрибутив с настроенным функционалом рассылки. Для использования описанного функционала на ваших проектах нужно провести работы:

  • Размещение компонента Форма подписки (bitrix:subscribe.form) в шаблоне сайта.
  • Настройка компонента на страницу редактирования подписки пользователя.
  • Создание, при необходимости, рубрик подписки.
  • Создать раздел управления подписками.
  • Размещение компонента Страница рассылок (bitrix:subscribe.index) и настройка ее на страницу редактирования подписки пользователя
  • Создание страницы редактирования подписки пользователя и размещение на ней компонента Страница редактирования подписки (bitrix:subscribe.edit).
  • Настройка модуля Подписка

Решение. Зададим идентификатор сущности к которой будут привязываться значения дополнительных свойств: MY_SUBSCRIPTION. В качестве уникального идентификатора объектов этой сущности будут выступать b_subscription.ID.

На странице Пользовательские поля (Настройки > Настройки продукта > Пользовательские поля) откроем форму создания нового поля.

Заполните поля:

  • Тип данных – Список
  • Объект – MY_SUBSCRIPTION
  • Код поля – UF_GENDER

Остальные поля не заполняем, нажимаем кнопку Применить.

На вкладке Список задаем возможные значения: Женский и Мужской. Применяем внесенные изменения.

Кастомизиция компонента subscribe.edit

После копирования компонента в свое пространство имён заменяем вызов на странице /personal/subscribe/subscr_edit.php на путь к копированному компоненту.

Для вывода значения пользовательских свойств подписки в файле component.php после

$arResult[“ALLOW_REGISTER”] = $bAllowRegister?”Y”:”N”;

добавляем чтение значений из базы данных

$arResult[“USER_PROPERTIES”] = $GLOBALS[“USER_FIELD_MANAGER”]->GetUserFields( “MY_SUBSCRIPTION”, $arResult[“ID”], LANGUAGE_ID);

В файле setting.php шаблона выводим примерно следующее:

<table> <?foreach ($arResult[“USER_PROPERTIES”] as $FIELD_NAME => $arUserField):?> <tr> <td><?echo $arUserField[“EDIT_FORM_LABEL”]?>:</td> <td><?$APPLICATION->IncludeComponent( “bitrix:system.field.edit”, $arUserField[“USER_TYPE”][“USER_TYPE_ID”], array( “bVarsFromForm” => false, “arUserField” => $arUserField ), null, array(“HIDE_ICONS”=>”Y”));?></td> </tr> <?endforeach;?> </table>

Для сохранения значений в базе данных в файле

component.php

после строк

if($ID>0) { … $res = $obSubscription->Update($ID, $arFields); … } else { … $ID = $obSubscription->Add($arFields); … }

добавляем код установки значений свойств

if($res && $ID > 0) { global $USER_FIELD_MANAGER; $arUserFields = $USER_FIELD_MANAGER->GetUserFields(“MY_SUBSCRIPTION”); $arFields = array(); foreach($arUserFields as $FIELD_ID => $arField) $arFields[$FIELD_ID] = $_REQUEST[$FIELD_ID]; $USER_FIELD_MANAGER->Update(“MY_SUBSCRIPTION”, $ID, $arFields); }

Для полноты действий у данного поля в административной части указываем:

  • Обязательное – Да
  • Подпись – Пол

Создайте новую подписку (или отредактируйте уже существующую) и укажите пол подписчика.

Теперь надо сделать так, чтобы #GENDER_HELLO# будет заменяться на Уважаемая/Уважаемый в зависимости от пола. Создаем обработчик события BeforePostingSendMail:

<? // файл /bitrix/php_interface/init.php // регистрируем обработчик AddEventHandler(“subscribe”, “BeforePostingSendMail”, Array(“MyClass”, “BeforePostingSendMailHandler”)); class MyClass { // создаем обработчик события “BeforePostingSendMail” function BeforePostingSendMailHandler($arFields) { $rs = CSubscription::GetByEmail($arFields[“EMAIL”]); if($ar = $rs->Fetch()) { global $USER_FIELD_MANAGER; $arUserFields = $USER_FIELD_MANAGER->GetUserFields(“MY_SUBSCRIPTION”, $ar[“ID”]); if($arUserFields[“UF_GENDER”][“VALUE”] == 1) $arFields[“BODY”] = str_replace(“#GENDER_HELLO#”, “Уважаемая”, $arFields[“BODY”]); elseif($arUserFields[“UF_GENDER”][“VALUE”] == 2) $arFields[“BODY”] = str_replace(“#GENDER_HELLO#”, “Уважаемый”, $arFields[“BODY”]); else $arFields[“BODY”] = str_replace(“#GENDER_HELLO#”, “”, $arFields[“BODY”]); } else { $arFields[“BODY”] = str_replace(“#GENDER_HELLO#”, “”, $arFields[“BODY”]); } return $arFields; } } ?>

  • Расширение пользовательских типов для пользовательских полей главного модуля. (блог)
  • Как прикрутить пользовательские свойства к своему модулю (блог)
  • Добавление типов данных “Связь с элементом” и “Связь с элементом в виде списка” (блог)

Назад в раздел

Находим подходящий стандартный тип поля

Естественно мы не будем писать всё с нуля и изобретать велосипеды, а подберём подходящий под наши задачи существующий класс реализующий нужный тип поля. Все классы пользовательских полей хранятся в главном модуле в папке /bitrix/modules/main/classes/general/ файлы классов имеют префикс usertype, здесь вы найдёте следующий набор классов:

  • usertypebool.php
  • usertypedate.php
  • usertypedbl.php
  • usertypeelement.php
  • usertypeenum.php
  • usertypefile.php
  • usertypeint.php
  • usertypesection.php
  • usertypestr.php
  • usertypestrfmt.php
  • usertypetime.php
  • usertypeurl.php

Как мы будем хранить значения? Очевидно что для пользователя это будет USER_ID, а для цвета строка, я предпочитаю hex формат  формат цвета. Следовательно нам потребуется скопировать и кастомизировать классы  usertypeenum (список) и usertypestr (строка). В принципе USER_ID можно реализовать на основе usertypeint, но давайте дадим администратору возможность удобного выбора пользователя, к тому же возможно нам потребуется сделать это поле множественным.

Работа с элементом как с массивом

Разберем различные примеры получения элементов. Простейший пример – это аналог CIBlockElement::GetByID:

$element = BitrixIblockElementsElementCatalogTable::getByPrimary($elementId, [ ‘select’ => [‘ID’, ‘NAME’, ‘DETAIL_TEXT’, ‘DETAIL_PICTURE’, ‘ARTNUMBER’],])->fetch();var_dump($element);/*array(8) { [“ID”]=> string(1) “4” [“NAME”]=> string(38) “Штаны Полосатый Рейс” [“DETAIL_TEXT”]=> string(?) “Брюки-клеш идеально сидят…” [“DETAIL_PICTURE”]=> string(2) “46” [“IBLOCK_ELEMENTS_ELEMENT_CATALOG_ARTNUMBER_ID”]=> string(1) “9” [“IBLOCK_ELEMENTS_ELEMENT_CATALOG_ARTNUMBER_IBLOCK_ELEMENT_ID”]=> string(1) “4” [“IBLOCK_ELEMENTS_ELEMENT_CATALOG_ARTNUMBER_IBLOCK_PROPERTY_ID”]=> string(1) “9” [“IBLOCK_ELEMENTS_ELEMENT_CATALOG_ARTNUMBER_VALUE”]=> string(11) “177-77-хх”}*/

Да, указывается код свойства без префикса “PROPERTY”. Правда здесь выходит какое-то безумное именование ключей. Немного получше можно сделать с помощью алиасов:

$element = BitrixIblockElementsElementCatalogTable::getByPrimary($elementId, [ ‘select’ => [‘ID’, ‘NAME’, ‘ARTNUMBER_’ => ‘ARTNUMBER’],])->fetch();var_dump($element);/* array(6) { [“ID”]=> string(1) “4” [“NAME”]=> string(38) “Штаны Полосатый Рейс” [“ARTNUMBER_ID”]=> string(1) “9” [“ARTNUMBER_IBLOCK_ELEMENT_ID”]=> string(1) “4” [“ARTNUMBER_IBLOCK_PROPERTY_ID”]=> string(1) “9” [“ARTNUMBER_VALUE”]=> string(11) “177-77-хх”}*/

Аналогом CIBlockElement::GetList будет getList из D7:

$elements = BitrixIblockElementsElementCatalogTable::getList([ ‘select’ => [‘ID’, ‘NAME’, ‘ARTNUMBER_’ => ‘ARTNUMBER’], ‘filter’ => [‘=ACTIVE’ => ‘Y’],])->fetchAll();foreach ($elements as $element) { // …}

Подробнее рассматривать работу с массивом не буду. Массив всегда можно вывести и посмотреть содержимое. А вот с объектами посложнее, ниже буду рассматривать работу как с объектом. Заменив fetchCollection на fetchAll, а fetchObject на fetchRow можно получить массив полей элемента и вывести то, что получилось. Для удобства именования можно использовать алиасы в select.

А теперь собственно прекрасная статья Анатолия Ерофеева

Новое ядро D7 в 1С-Битрикс: Управление сайтом решительно замещает старое. Все чаще использование привычных методов и классов приводит к предупреждению от IDE “Method/class is deprecated”. Предлагаю “знать врага в лицо” и провести небольшой обзор таких классов D7, которые уже сейчас можно и нужно использовать, чтобы не прослыть в среде разработчиков неотесанным неандертальцем. Но замечу, что ядро D7 – это не просто рефакторинг, это смена подхода к написанию кода.

В конце статьи собраны все аналоги, которые могут понадобиться разработчику.

Подключение стилей и скриптов

CMain::AddHeadScript , CMain::SetAdditionalCss , CMain::AddHeadString

Давным-давно в далекой-далекой версии Битрикса разработчики вставляли стили и скрипты шаблона в документ банальными тегами <script> и <link>. Потом в фаворе оказались названные выше отложенные функции. Сейчас устарели и они. Нынче на дворе 2016 год и подключать надо так:

// Old school
$APPLICATION->AddHeadScript(SITE_TEMPLATE_PATH . “/js/fix.js”);
$APPLICATION->SetAdditionalCSS(SITE_TEMPLATE_PATH . “/styles/fix.css”);
$APPLICATION->AddHeadString(“<link href=’http://fonts.googleapis.com/css?family=PT+Sans:400&subset=cyrillic’ rel=’stylesheet’ type=’text/css’>”);

// D7
use BitrixMainPageAsset;

Asset::getInstance()->addJs(SITE_TEMPLATE_PATH . “/js/fix.js”);
Asset::getInstance()->addCss(SITE_TEMPLATE_PATH . “/styles/fix.css”);
Asset::getInstance()->addString(“<link href=’http://fonts.googleapis.com/css?family=PT+Sans:400&subset=cyrillic’ rel=’stylesheet’ type=’text/css’>”);

Эти методы динамические, а класс реализует паттерн “одиночка” (Singletone) и обратиться к объекту можно через BitrixMainPageAsset::getInstance() .

По слухам, этот класс может быть в скором времени переписан, так что необходимо держать руку на пульсе.

Срочно в номер: на днях была опубликована документация по новому способу подключения JS и CSS в шаблонах компонентов.

Подключение модулей

CModule::IncludeModule , CModule::IncludeModuleEx

Уже многие выучили, что вместо старого доброго CModule для подключения модулей нужно применять новый бодрый BitrixMainLoader .

// Old school
CModule::IncludeModule(“iblock”);
CModule::IncludeModuleEx(“intervolga.tips”);

// D7
use BitrixMainLoader;

Loader::includeModule(“iblock”);
Loader::includeSharewareModule(“intervolga.tips”);

Локализация

GetMessage , IncludeModuleLangFile , IncludeTemplateLangFile

Чтобы быть стильным-модным-молодежным рекомендуется пользоваться следующим кодом для обращения к языковым файлам и переменным:

// Old school
IncludeTemplateLangFile(__FILE__);
echo GetMessage(“INTERVOLGA_TIPS.TITLE”);

// D7
use BitrixMainLocalizationLoc;

Loc::loadMessages(__FILE__);
echo Loc::getMessage(“INTERVOLGA_TIPS.TITLE”);

Настройки модулей

COption::SetOptionInt , COption::SetOptionString , COption::GetOptionInt , COption::GetOptionString , COption::RemoveOption

Претерпел изменения и код для работы с чтением и записью настроек модулей. На смену классу COption пришел BitrixMainConfigOption :

// Old school
COption::SetOptionString(“main”, “max_file_size”, “1024”);
$size = COption::GetOptionInt(“main”, “max_file_size”);
COption::RemoveOption(“main”, “max_file_size”, “s2”);

// D7
use BitrixMainConfigOption;

Option::set(“main”, “max_file_size”, “1024”);
$size = Option::get(“main”, “max_file_size”);
Option::delete(“main”, array(
    “name” => “max_file_size”,
    “site_id” => “s2”
    )
);

Пропало разделение методов на int и string, а при удалении теперь используется массив-фильтр.

В новом классе есть несколько совершенно новых методов, не имеющих “старых” аналогов, так что самостоятельное изучение исходного кода приветствуется.

Файловая структура

CheckDirPath , DeleteDirFilesEx , RewriteFile

Тут нынче раздолье для ООП-программиста. Для работы с файлами, папками и всем прочим – отдельные классы, все типизировано и напоминает Java. Самые “главные” классы здесь – BitrixMainIODirectory и BitrixMainIOFile (ну и немного BitrixMainIOPath ).

// Old school
CheckDirPath($_SERVER[“DOCUMENT_ROOT”] . “/foo/bar/baz/”);
RewriteFile(
    $_SERVER[“DOCUMENT_ROOT”] . “/foo/bar/baz/1.txt”,
    “hello from old school!”
);
DeleteDirFilesEx(“/foo/bar/baz/”);

// D7
use BitrixMainApplication;
use BitrixMainIODirectory;
use BitrixMainIOFile;

Directory::createDirectory(
    Application::getDocumentRoot() . “/foo/bar/baz/”
);
File::putFileContents(
Application::getDocumentRoot() . “/foo/bar/baz/1.txt”,
    “hello from D7”
);
Directory::deleteDirectory(
    Application::getDocumentRoot() . “/foo/bar/baz/”
);

Необходимо только запомнить, что DeleteDirFilesEx принимал путь от корня сайта, а его аналог принимает абсолютный путь к файлу от корня сервера.

Обратите внимание : вместо $_SERVER[“DOCUMENT_ROOT”] сейчас можно использовать BitrixMainApplication::getDocumentRoot() .

Классы для работы с файловой системой умеют многое, в этом вы можете убедиться сами, изучив исходники.

ORM-классы

Их реально много. Их просто нужно “знать в лицо”, так как это будет основной инструмент на многие годы, как когда-то был CIBlockElement::GetList сотоварищи. В таблице в конце статьи я приведу основные ORM-классы, на которые стоит обратить внимание уже сегодня.

Рейтинг
( 1 оценка, среднее 5 из 5 )
Загрузка ...