Bitrix - D7 - аналоги любимых функций в 1С-Битрикс
Войти

Bitrix - D7 - аналоги любимых функций в 1С-Битрикс

Bitrix - D7-аналоги любимых функций в 1С-Битрикс

Справочник API D7: dev.1c-bitrix.ru

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

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

1
2
3
4
5
6
<?php 

//Подключение стилей и скриптов
CMain::AddHeadScript CMain::SetAdditionalCss CMain::AddHeadString

?>

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php 

// 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 в шаблонах компонентов.

1
2
3
4
5
6
7
<?php 

<class="zag_1">Подключение модулей</p>

CModule::IncludeModule CModule::IncludeModuleEx

?>

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

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php 

// Old school 
CModule::IncludeModule("iblock"); 
CModule::IncludeModuleEx("picht.tips"); 

// D7 
use BitrixMainLoader

Loader::includeModule("iblock"); 
Loader::includeSharewareModule("picht.tips");

?>

Локализация

GetMessage, IncludeModuleLangFile, IncludeTemplateLangFile Чтобы быть стильным-модным-молодежным рекомендуется пользоваться следующим кодом для обращения к языковым файлам и переменным:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php 

// 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 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php 

// 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, а при удалении теперь используется массив-фильтр.

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

Кеширование

1
2
3
4
5
<?php 

CPHPCache
::StartDataCache CPHPCache::InitCache CPHPCache::GetVars CPHPCache::EndDataCache CPHPCache::AbortDataCache

?>
Новый класс BitrixMainDataCache почти ничем не отличается в обращении от старого CPHPCache .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php 

// Old school 
$cache = new CPHPCache(); 
if (
$cache->InitCache($cacheTime$cacheId$cacheDir)) 

    
$result $cache->GetVars(); 

elseif(
$cache->StartDataCache()) 

    
$result = array(); 
    
// ... 
    
if ($isInvalid
    { 
        
$cache->AbortDataCache(); 
    } 
    
// ... 
    
$cache->EndDataCache($result); 


// D7 
$cache BitrixMainDataCache::createInstance(); 
if (
$cache->initCache($cacheTime$cacheId$cacheDir)) 

    
$result $cache->getVars(); 

elseif (
$cache->startDataCache()) 

    
$result = array(); 
    
// ... 
    
if ($isInvalid
    { 
        
$cache->abortDataCache(); 
    } 
    
// ... 
    
$cache->endDataCache($result); 
}
 
?>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?php 

// Old school 
$handler AddEventHandler("main"
    
"OnUserLoginExternal"
    array( 
        
"IntervolgaTestEventHandlersMain"
        
"onUserLoginExternal" 
    

); 
RemoveEventHandler
    
"main"
    
"OnUserLoginExternal"
    
$handler 
); 
RegisterModuleDependences
    
"main"
    
"OnProlog"
    
$this->MODULE_ID
    
"IntervolgaTestEventHandlers"
    
"onProlog" 
); 
UnRegisterModuleDependences
    
"main"
    
"OnProlog"
    
$this->MODULE_ID
    
"IntervolgaTestEventHandlers"
    
"onProlog" 
); 

$handlers GetModuleEvents("main""OnProlog"true); 

// D7 
use BitrixMainEventManager

$handler EventManager::getInstance()->addEventHandler
    
"main"
    
"OnUserLoginExternal"
    array( 
        
"IntervolgaTestEventHandlersMain"
        
"onUserLoginExternal" 
    

); 
EventManager::getInstance()->removeEventHandler
    
"main"
    
"OnUserLoginExternal"
    
$handler 
); 
EventManager::getInstance()->registerEventHandler
    
"main"
    
"OnProlog"
    
$this->MODULE_ID
    
"IntervolgaTestEventHandlers"
    
"onProlog" 
); 
EventManager::getInstance()->unRegisterEventHandler
    
"main"
    
"OnProlog"
    
$this->MODULE_ID
    
"IntervolgaTestEventHandlers"
    
"onProlog" 
); 
$handlers EventManager::getInstance()->findEventHandlers("main""OnProlog");

?>

BitrixMainEventManager , так же как BitrixMainPageAsset , реализует паттерн Одиночка, обращаться к нему нужно через getInstance().

Важное замечание: в обработчики, зарегистрированные с помощью addEventHandler в качестве аргумента будет передан объект события ( BitrixMainEvent ). Если хотите, чтобы передавались старые добрые аргументы, нужно использовать addEventHandlerCompatible . Аналогично с registerEventHandler и registerEventHandlerCompatible .

Файловая структура 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() . Классы для работы с файловой системой умеют многое, в этом вы можете убедиться сами, изучив исходники. Исключения CMain::ThrowException , CMain::ResetException , CMain::GetException Открою небольшой секрет: в нашем дружном коллективе возник локальный холивар. Мы спорили, стоит ли помещать в эту статью раздел про исключения и обработку ошибок. Ведь тут не просто одни методы заменили другие – тут изменился подход (о чем я говорил в начале статьи), были переосмыслены некоторые базовые принципы многих классов. Есть две причины, почему этот раздел все-таки опубликован: Это важная тема, и говоря о переходе на D7 про нее нельзя не упомянуть Автор статьи все-таки я :P Итак, одним из наиболее существенных изменений в D7 стала обработка ошибок при помощи механизма исключений (полное соблюдение религии исключений в php ). Если происходит ошибка – выбрасываем исключение. Если хотим обработать ошибку – ловим исключение. Базовый класс для всех исключений в системе: BitrixMainSystemException .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php 

// Old school 
global $APPLICATION
$APPLICATION->ResetException(); 
$APPLICATION->ThrowException("Error"); 
//... 
if ($exception $APPLICATION->GetException()) 

    echo 
$exception->GetString(); 


// D7 
use BitrixMainSystemException

try 

    
// ... 
    
throw new SystemException("Error"); 

catch (
SystemException $exception

    echo 
$exception->getMessage(); 
}

?>

Отладка AddMessage2Log , mydump

Ах, сколько раз выручал бывалого разработчика этот метод ( AddMessage2Log ). Неизменный товарищ при отладке ajax-запросов, крон-файлов и всего, невидимого глазу администратора. Но сегодня устарел и он, а на смену ему спешат два новых “молодца”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php 

// Old school 
define("LOG_FILENAME"$_SERVER["DOCUMENT_ROOT"]."/bitrix/log-intervolga.txt"); 

AddMessage2Log($_SERVER); 
echo 
"<pre>" mydump($_SERVER) . "</pre>"

// D7 
use BitrixMainDiagDebug

Debug::dumpToFile($_SERVER); 
// or 
Debug::writeToFile($_SERVER); 

Debug::dump($_SERVER);
Первый для любителей var_dump второй для адептов print_r ’а.

?>
Так же в этом классе есть несколько совершенно новых методов, не имеющих аналогов в старом ядре. Например, методы для измерения времени:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php 

// D7 
use BitrixMainDiagDebug
Debug::startTimeLabel("foo"); 
foo(); 
Debug::endTimeLabel("foo"); 

Debug::startTimeLabel("bar"); 
bar(); 
Debug::endTimeLabel("bar"); 
         
print_r(Debug::getTimeLabels());
Почтовые события
CEvent
::Send CEvent::SendImmediate

?>

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php 

// Old school 
CEvent::Send
    
"NEW_USER"
    
"s1"
    array( 
        
"EMAIL" => "info@intervolga.ru"
        
"USER_ID" => 42 
    

); 

// D7 
use BitrixMainMailEvent
Event::send(array( 
    
"EVENT_NAME" => "NEW_USER"
    
"LID" => "s1"
    
"C_FIELDS" => array( 
        
"EMAIL" => "info@intervolga.ru"
        
"USER_ID" => 42 
    
), 
));
Работа с GETи POST-параметрами страницы
$_GET 
$_POST $_REQUEST

?>

Чтобы избавиться от глобальных переменных в коде (суперглобальных в том числе) в D7 изобрели класс BitrixMainHttpRequest . Забирать get- и post-переменные теперь можно через него.

// Old school $name = $_POST["name"]; $email = htmlspecialchars($_GET["email"]); // D7 use BitrixMainApplication; $request = Application::getInstance()->getContext()->getRequest(); $name = $request->getPost("name"); $email = htmlspecialchars($request->getQuery("email")); Конструировать объект самому не нужно, добраться до него можно через приложение и контекст (как в примере кода выше). Работа с cookie CMain::set_cookie , CMain::get_cookie Класс CMain слишком много себе позволяет. Он и компоненты подключал, и CSS/JS регистрирует, и хлебные крошки собирает, и т.п. В этом разделе мы рассмотрим, куда “сбежали” методы работы с куками. В старом ядре было 2 метода: для создания и для получения кук. Теперь всё стало гораздо глубже: задавать куки нужно через класс “ответа сервера” – BitrixMainHttpResponse , получать их нужно через класс “запроса к серверу” – BitrixMainHttpRequest . // Old school global $APPLICATION; $APPLICATION->set_cookie("TEST", 42, false, "/", "example.com"); // Cookie будет доступна только на следующем хите! echo $APPLICATION->get_cookie("TEST"); // D7 use BitrixMainApplication; use BitrixMainWebCookie; $cookie = new Cookie("TEST", 42); $cookie->setDomain("example.com"); Application::getInstance()->getContext()->getResponse()->addCookie($cookie); // Cookie будет доступна только на следующем хите! echo Application::getInstance()->getContext()->getRequest()->getCookie("TEST"); Также работа с куками может вестись силами класса BitrixMainWebHttpClient , но это совсем другая история . Важное замечание: запись куки, добавленной через D7, произойдет только при подключении эпилога (там вызывается метод BitrixMainHttpResponse::flush() ) Работа со ссылками CMain::GetCurPageParam , DeleteParam

Для работы со ссылками в ядре D7 есть отдельный класс: BitrixMainWebUri . Правда, работа с ним не так “компактна”, как с его предшественником. Но это лишь следствие того, что в этом классе соблюдается принцип “1 метод – 1 ответственность”.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php 

// Old school 
global $APPLICATION
$redirect $APPLICATION->GetCurPageParam("foo=bar", array("baz")); 

// D7 
use BitrixMainApplication
use 
BitrixMainWebUri

$request Application::getInstance()->getContext()->getRequest(); 
$uriString $request->getRequestUri(); 
$uri = new Uri($uriString); 
$uri->deleteParams(array("baz")); 
$uri->addParams(array("foo" => "bar")); 
$redirect $uri->getUri();

?>

ORM-классы

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

Запросы к БД CDatabase::Query

Хоть это и не рекомендуется, но возможность поработать с БД прямыми запросами в продукте остается. Теперь доступ получается не через глобальный объект $DB класса CDatabase , а через BitrixMainDBConnection . “Добираться” до подключения нужно через BitrixMainApplication:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php 

// Old school 
global $DB
$record $DB->Query("select 1+1;")->Fetch(); 
AddMessage2Log($record); 

// D7 
use BitrixMainApplication
use 
BitrixMainDiagDebug

$record Application::getConnection() 
->
query("select 1+1;"
->
fetch(); 
Debug::writeToFile($record);

?>
Хозяйке на заметку : больше про ORM и работу с БД в D7 можно почерпнуть из другой нашей статьи . Итоговая таблица аналогов старых методов и классов в новом ядре D7 (с примерами вызова)
Было (старое ядро) Стало (новое ядро D7)
CMain::AddHeadScript Bitrix\Main\Page\Asset::addJs
CMain::SetAdditionalCss Bitrix\Main\Page\Asset::addCss
CMain::AddHeadString Bitrix\Main\Page\Asset::addString
CModule::IncludeModule Bitrix\Main\Loader::includeModule
CModule::IncludeModuleEx Bitrix\Main\Loader::includeSharewareModule
GetMessage Bitrix\Main\Localization\Loc::getMessage
GetMessage Bitrix\Main\Localization\Loc::getMessage
BitrixMainLocalizationLoc::getMessage IncludeModuleLangFile , IncludeTemplateLangFile BitrixMainLocalizationLoc::loadMessages COption::SetOptionInt , COption::SetOptionString , BitrixMainConfigOption::set COption::GetOptionInt , COption::GetOptionString BitrixMainConfigOption::get COption::RemoveOption BitrixMainConfigOption::delete CPHPCache::StartDataCache BitrixMainDataCache::startDataCache CPHPCache::InitCache BitrixMainDataCache::initCache CPHPCache::GetVars BitrixMainDataCache::getVars CPHPCache::EndDataCache BitrixMainDataCache::endDataCache CPHPCache::AbortDataCache BitrixMainDataCache::abortDataCache AddEventHandler BitrixMainEventManager::addEventHandler (новый формат), BitrixMainEventManager::addEventHandlerCompatible RemoveEventHandler BitrixMainEventManager::removeEventHandler (новый формат), BitrixMainEventManager::registerEventHandlerCompatible RegisterModuleDependences BitrixMainEventManager::registerEventHandler UnRegisterModuleDependences BitrixMainEventManager::unRegisterEventHandler GetModuleEvents BitrixMainEventManager::findEventHandlers CheckDirPath BitrixMainIODirectory::createDirectory DeleteDirFilesEx BitrixMainIODirectory::deleteDirectory RewriteFile BitrixMainIOFile::putFileContents CMain::ThrowException BitrixMainSystemException CMain::ResetException BitrixMainSystemException CMain::GetException BitrixMainSystemException AddMessage2Log BitrixMainDiagDebug::dumpToFile, BitrixMainDiagDebug::writeToFile mydump BitrixMainDiagDebug::dump CEvent::Send BitrixMainMailEvent::send CEvent::SendImmediate BitrixMainMailEvent::sendImmediate $_REQUEST BitrixMainHttpRequest::get $_GET BitrixMainHttpRequest::getQuery $_POST BitrixMainHttpRequest::getPost CMain::set_cookie BitrixMainHttpResponse::addCookie CMain::get_cookie BitrixMainHttpRequest::getCookie CMain::GetCurPageParam BitrixMainWebUri::addParams, BitrixMainWebUri::deleteParams, BitrixMainWebUri::getUri DeleteParam BitrixMainWebUri::deleteParams, BitrixMainWebUri::getUri CDatabase::Query BitrixMainDBConnection::query ORM-классы Класс в старом ядре Класс в новом ядре D7 Таблица БД CUser BitrixMainUserTable b_user CFile BitrixMainFileTable b_file CGroup BitrixMainGroupTable b_group CSite BitrixMainSiteTable b_lang CIBlockElement BitrixIblockElementTable b_iblock_element CIBlock BitrixIblockIblockTable b_iblock CIBlockProperty BitrixIblockPropertyTable b_iblock_property CIBlockSection BitrixIblockSectionTable b_iblock_section CIBlockPropertyEnum BitrixIblockPropertyEnumerationTable b_iblock_property_enum CCatalogStore BitrixCatalogStoreTable b_catalog_store CCatalogProduct BitrixCatalogProductTable b_catalog_product CCatalogGroup BitrixCatalogGroupTable b_catalog_group CSaleOrder BitrixSaleInternalsOrderTable b_sale_order CSaleBasket BitrixSaleInternalsBasketTable b_sale_basket CSaleOrderProps BitrixSaleInternalsOrderPropsTable b_sale_order_props CSaleOrderPropsValue BitrixSaleInternalsOrderPropsValueTable b_sale_order_props_value

Выводы

Складывается интересная ситуация. Компания 1С-Битрикс активно рекламирует новое ядро D7, на каждой конференции все чаще слышны фразы “компонент/модуль полностью переписан на новом ядре, классах и т.п.”, старый код все чаще отмечается как @deprecated . Но при всем при этом никакой документации нет. Документация посвящена только старому ядру и если нужно познакомиться с D7 – то нужно держать руку на пульсе событий: читать исходники, форумы , блоги , общаться с техподдержкой, изучать официальные видеокурсы( Разработка на D7.Введение и D7. Разработка собственного модуля ). С одной стороны, это может повысить “порог вхождения” в “клуб программистов D7” и сделать их еще более бородатыми, с другой – может отпугнуть новичков.

Будем надеяться, что исчерпывающая документация по новому ядру все-таки появится и мы (программисты, пользователи и разработчики 1С-Битрикс: Управление сайтом) пойдем в светлое будущее, где уже маячат PHP 7, EcmaScript 6 и другие радости web-технологий.

Ссылки по теме:

  1. 1. d7 - новое ядро
  2. 1. abraxabra.ru
Теги:
php