334  /  382
Справочник

Работа с БД

Просмотров: 115902
Дата последнего изменения: 15.11.2023
Роберт Басыров
Сложность урока:
4 уровень - сложно, требуется сосредоточиться, внимание деталям и точному следованию инструкции.
1
2
3
4
5
Недоступно в лицензиях:
Ограничений нет

Общая архитектура классов API для работы с базами данных:

  • Пул соединений Bitrix\Main\Data\ConnectionPool управляет соединениями, параметры которых настроены в файле настроек .settings.php. В пуле есть соединение по умолчанию и может быть набор дополнительных именованных соединений. Например, соединений к другой базе данных.
  • Конкретные классы соединений наследуют абстрактный класс Bitrix\Main\DB\Connection. Для разных типов баз данных реализованы разные конкретные классы.
  • Конкретные классы формирования SQL запросов, наследующие Bitrix\Main\DB\SqlHelper. Они помогают сформировать запрос не опускаясь до синтаксиса конкретной базы данных.
  • Конкретные классы для работы с результатом выполнения запроса, наследующие Bitrix\Main\DB\Result.

Эти классы позволяют работать с базами данных на низком уровне, но это необходимо в небольшом числе случаев. Предпочтительно работать через ORM, которая позволяет программировать только на уровне бизнес-логики.

  • Получение соединения, именованные соединения
  • Разные формы вызова выполнения запроса
  • Получение результатов запроса
  • Работа со временем
  • Работа с несколькими базами данных
  • Поддержка нового типа БД

  • Получение соединения, именованные соединения

    Получить соединение можно через приложения, которое, кроме всего прочего, является точкой входа. С этой точки входа можно получить экземпляры "звездных" объектов для данного приложения, которые нужны всем (или почти всем) страницам или компонентам данного приложения.

    $connection = Bitrix\Main\Application::getConnection();
    $sqlHelper = $connection->getSqlHelper();
    
    $sql = "SELECT ID FROM b_user WHERE LOGIN = '".$sqlHelper->forSql($login, 50)."'";
    
    $recordset = $connection->query($sql);
    while ($record = $recordset->fetch())
    {
    	***

    Разные формы вызова выполнения запроса

    Соответственно, через приложение выполняется запрос в разной форме: просто запрос, запрос с указанием лимита на записи, скалярный запрос либо запрос "вообще".

    $result1 = $connection->query($sql);
    $result2 = $connection->query($sql, $limit);
    $result3 = $connection->query($sql, $offset, $limit);
    
    $cnt = $connection->queryScalar("SELECT COUNT(ID) FROM table");
    
    $connection->queryExecute("INSERT INTO table (NAME, SORT) VALUES ('Название', 100)")

    Получение результатов запроса

    $connection = Bitrix\Main\Application::getConnection();
    $sqlHelper = $connection->getSqlHelper();
    
    $sql = "SELECT ID FROM b_user WHERE LOGIN = '".$sqlHelper->forSql($login, 50)."' ";
    
    $recordset = $connection->query($sql);
    while ($record = $recordset->fetch())
    {
    	***

    Типизированные данные возвращаются сразу в виде типа, а не в виде строк или чисел.

    Модификация результата:

    $connection = \Bitrix\Main\Application::getConnection();
    $recordset = $connection->query("select * from b_iblock_element", 10);
    $recordset->addFetchDataModifier(
    	function ($data)
    	{
    		$data["NAME"] .= "!";
    		return $data;
    	}
    );
    
    while ($record = $recordset->fetch(\Bitrix\Main\Text\Converter::getHtmlConverter()))
    	{
    		$data[] = $record;
    	}

    Результат можно модифицировать, применить конвертер к результатам сразу, например, подготовить к выводу в XML, и так далее.


    Работа со временем

    При проектировании своей БД возникает вопрос, какой тип данных использовать: datetime или timestamp? При работе с БД приведение времени к GMT является минимально необходимым. Чтобы меньше зависеть от настроек сервера, лучше использовать datetime. В этом случае текущее значение времени придется получать на PHP.


    Работа с несколькими базами данных

    В рамках работы ORM можно работать с несколькими базами данных. Для этого в файле /bitrix/.settings.php в секции connections создается несколько записей для работы с базой:

    'default' =>
    	array(
    		'className' => '\\Bitrix\\Main\\DB\\MysqlConnection',
    		'host' => 'localhost', 
    		'database' => 'site', 
    		'login' => 'user', 
    		'password' => 'passwd',
    		'options' => 2,
    	),
    'old_db' =>
    	array(
    		'className' => '\\Bitrix\\Main\\DB\\MysqlConnection',
    		'host' => 'localhost',
    		'database' => 'old_db',
    		'login' => 'user',
    		'password' => 'passwd',
    		'options' => 2,
     ), 

    Таким образом подключены 2 базы: default (по умолчанию Bitrix Framework использует это подключение) и old_db (указаны параметры подключения ко 2-й базе данных). Обращаться к old_db нужно так:

    $connection = Bitrix\Main\Application::getConnection('old_db');
    $sqlHelper = $connection->getSqlHelper();
    
    $sql = "SELECT ID FROM b_user WHERE LOGIN = '".$sqlHelper->forSql($login, 50)."' ";
    
    $recordset = $connection->query($sql);
    while ($record = $recordset->fetch())
    {
    	*** 

    В параметре include_after_connected можно указать путь к файлу, который будет подключен и выполнен после первого соединения с дополнительной БД:

    'old_db' => array(
    	'className' => '\\Bitrix\\Main\\DB\\MysqlConnection',
    	'host' => 'localhost',
    	'database' => 'old_db',
    	'login' => 'user',
    	'password' => 'passwd',
    	'options' => 2,
    	'include_after_connected' => $_SERVER["DOCUMENT_ROOT"].'/local/php_interface/after_connect_d7_old_db.php',
    ),
    

    Сам файл after_connect_d7_old_db.php

    <?
    $connectionOld = \Bitrix\Main\Application::getConnection("old_db");
    $connectionOld->queryExecute("SET NAMES 'utf8'");
    $connectionOld->queryExecute("SET collation_connection = 'utf8_unicode_ci'");
    ?>

    Для привязки сущности ORM к конкретному соединению переопределите в своем *Table классе метод Bitrix\Main\ORM\Data\DataManager::getConnectionName().


    Поддержка нового типа БД

    В редких случаях возникает необходимость подключения баз данных к которым невозможно использовать встроенный драйвер для PHP (например, у заказчика чрезвычайно устаревшая (или наоборот, слишком свежая) версия СУБД. Чтобы добавить в Bitrix Framework поддержку нового типа БД, необходимо:

    • Создать класс подключения (наследник Bitrix\Main\DB\Connection). В нем определить все базовые операции с БД: подключение, отключение, выполнение произвольного запроса, работу с транзакциями.
    • Создать класс SQL-хелпер (наследник Bitrix\Main\DB\SqlHelper) и возвращать его экземпляр в методе createSqlHelper. Класс предназначен для самой низкоуровневой работы с БД: добавляет экранирование, работает с датами, предоставляет доступ к базовым SQL-функциям и так далее.
    • Создать класс для результата выборки (наследник Bitrix\Main\DB\Result). В нем требуется определить методы-обертки над традиционными функциями работы с результатом выборки.

    Примечание: реальный пример: использование ORM для подключения из PHP к MSSQL в Linux от компании "Интерволга".




    44
    Курсы разработаны в компании «1С-Битрикс»

    Если вы нашли неточность в тексте, непонятное объяснение, пожалуйста, сообщите нам об этом в комментариях.
    Развернуть комментарии