Наверх

База данных

Класс с функциями для работы с базой данных – DB – определен в файле includes/database.php.

Все функции статичные, их можно вызвать из любого файла в формате: DB::имя_функции().

Пример:

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

$result = DB::query("SELECT fio FROM diafan_users WHERE role_id=%d", $role_id);

Указывая таблицу, можно не писать префикс diafan_users, а написать {users}.

$result = DB::query("SELECT fio FROM {users} WHERE role_id=%d", $role_id);

Обратите внимание, в примере мы не пишем WHERE role_id=$role_id, а пишем WHERE role_id=%d. Это сделано для безопасности, чтобы можно было спокойно делать запросы с внешними переменными типа $_GET["role_id"].

Для фильтрации аргументов SQL-запроса вместо данных передаются маски, а данные передаются в качестве дополнительных аргументов для функций DB::query(), DB::query_result() и DB::query_range() в порядке, в котором они следуют в SQL-запросе. Существуют следующие маски:

  • %d – число,
  • %s – строка,
  • %h – строка без HTML кода,
  • %% – символ %,
  • %f – число с плавающей точкой,
  • %b – файлы

Название таблицы пишется без префикса в фигурных скобках.

Пример:

{attachments}

Переводимые переменные в SQL-запросе пишутся в квадратных скобках.

Пример:

[name]

Для проверки, правильно ли сформировался SQL-запрос и какие данные в него подставлены, запрос можно вывести на экран. Для этого нужно перед запросом написать DEV и включить режим разработки.

Пример:

$text = DB::query_result("DEV SELECT [text] FROM {shop_category} WHERE id=%d", $cat_id);

Методы

boolean connect ([string $db_url = DB_URL], [boolean $check = false]) – Подключается к базе данных.

  • string $db_url: данные для подключения к базе данных
  • boolean $check: проверка соединения
Подключение к базе данных происходит автоматически при первом SQL-запросе. Данные для подключения беруться из константы DB_URL, определенной в файле config.php.

void close () – Закрывает ранее открытое соединение.

Пример:

// закрываем текущее соединение
DB::close();

//подключимся к другой базе данных и запросим список пользователей
DB::connect("mysql://root:@localhost/otherdb");
$users = DB::query_fetch_all("SELECT id, fio FROM otherdb_users");

// закрываем новое соединение
DB::close();

//возвращаем подключение обратно
DB::connect(DB_URL);

boolean set_charset (string $charset) – Задает набор символов по умолчанию.

  • string $charset: набор символов, который необходимо установить.

Пример:

DB::set_charset('utf8');

mixed query (string $query) – Отправляет запрос к базе данных.

  • string $query: текст запроса

Пример:

// вставляем данные в таблицу diafan_clauses
DB::query("INSERT INTO {clauses} ([name], [act], created) VALUES ('%h', '%d', %d)", $_POST["name"], $_POST["act"], time());

mixed query_without_prefix (string $query) – Отправляет запрос к базе данных без замены префикса.

  • string $query: текст запроса

Пример:

// используется при импорте базы данных, чтобы SQL-запрос не преобразовывались
DB::query_without_prefix("INSERT INTO diafan_config (name, module_name, value) VALUES ('images_variations_element', 'news', 'a:2:{i:0;a:2:{s:4:\"name\";s:6:\"medium\";s:2:\"id\";i:1;}i:1;a:2:{s:4:\"name\";s:5:\"large\";s:2:\"id\";i:3;}}')");

resource query_range (string $query) – Отправляет запрос к базе данных с лимитом на количество получаемых в результате рядов.

  • string $query: текст запроса

Предпочтительно использовать функцию query_range_fetch_all().

Пример:

// получаем имена трех картинок, прикрепленных к товару ID=5
$result = DB::query_range("SELECT name FROM {image} WHERE module_name='shop' AND element_id=%d AND element_type='element'", 5, 0, 3);

Подобные запросы вы можете часто встретить в файлах *.model.php, где производится выборка данных для списков, а также в модулях, поддерживающих постраничную навигацию.

Пример:

// запрос фотографий в альбоме ID=5 для списка
// в файле modules/photo/photo.model.php
$result = DB::query_range("SELECT * FROM {photo} WHERE cat_id=5 ORDER BY sort DESC", $this->diafan->_paginator->polog, $this->diafan->_paginator->nastr);

$this->diafan->_paginator->polog, $this->diafan->_paginator->nastr в данном случае выступают в роли начального и конечного индекса выборки.

mixed result (resource $result, [integer $row = 0]) – Получает результирующие данные.

  • resource $result: обрабатываемый результат запроса
  • integer $row: номер получаемого ряда из результата

Пример:

// выполняем SQL-запрос к базе данных
$result = DB::query("SELECT id FROM {users} WHERE name='admin' LIMIT 1");
// получаем результат
$id = DB::result($result);

void free_result (resource $result) – Освобождает память от результата запроса.

  • resource $result: обрабатываемый результат запроса

Пример:

// выполняем SQL-запрос к базе данных
$result = DB::query("SELECT id FROM {users} WHERE name='admin' LIMIT 1");

// получаем результат
$id = DB::result($result);

// освобождаем результат
DB::free_result($result);

В примере три операции можно заменить вызовом функции query_result().

Пример:

$id = DB::query_result("SELECT id FROM {users} WHERE name='admin' LIMIT 1");

Есть аналогичные объединяющие функции для получения массива данных с одной или несколькими строками. Поэтому функции result() и free_result() вне класса DB не используются.

array fetch_row (resource $result) – Извлекает результирующий ряд как пронумерованный массив.

  • resource $result: обрабатываемый результат запроса

Пример:

// запрашиваем в базе данных и выводим список товаров
$result = DB::query("SELECT id, [name] FROM {shop}");
echo
'Товары: ';
while (
$row = DB::fetch_row($result))
{
    echo
'ID: '.$row[0].' name: '.$row[1]."\n";
}
DB::free_result($result);

array fetch_array (resource $result) – Извлекает результирующий ряд как массив.

  • resource $result: обрабатываемый результат запроса

Предпочтительно использовать функцию query_fetch_array() и аналогичные.

Пример:

// запрашиваем в базе данных и выводим список способов доставки
$result = DB::query("SELECT [name] FROM {shop_delivery} ORDER BY sort ASC");
echo
'Способы доставки:';
while (
$row = DB::fetch_array($result))
{
    echo
$row["name"] . <br>;
}
DB::free_result($result);

object fetch_object (resource $result) – Извлекает результирующий ряд как объект.

  • resource $result: обрабатываемый результат запроса

Пример:

// запрашиваем в базе данных и выводим список новостей
$result = DB::query("SELECT [name], [anons] FROM {news} ORDER BY created DESC");
echo
'Новости:';
while (
$row = DB::fetch_object($result))
{
    echo
'Название: '$row->name.' анонс: '.$row->anons;
}
DB::free_result($result);

integer num_rows (resource $result) – Получает количество рядов в результате.

  • resource $result: обрабатываемый результат запроса

Пример:

// выводим количество новостей старше текущей даты
$result = DB::query("SELECT id FROM {news} WHERE created>%d", time());
echo
DB::num_rows($result);
DB::free_result($result);

integer insert_id () – Возвращает автоматически генерируемый ID, используя последний запрос.

Пример:

// определяем ID только что добавленного пользователя
DB::query("INSERT INTO {users} (name) VALUES ('admin')");
$user_id = DB::insert_id();

// сокращенная запись
$user_id = DB::query("INSERT INTO {users} (name) VALUES ('admin')");

integer affected_rows () – Возвращает число затронутых прошлой операцией рядов.

mixed query_result () – Получает результирующие данные из SQL-запроса.

Пример:

// получаем описание текущей категории из БД
$text = DB::query_result("SELECT [text] FROM {shop_category} WHERE id=%d", $this->diafan->cat);

mixed query_fetch_array () – Получает результирующий ряд как массив из SQL-запроса.

Пример:

// запрашиваем в базе данных пользователя ID=4
$user = DB::query_fetch_array("SELECT * FROM {users} WHERE id=4");
echo
'Имя: '.$user["fio"];
echo
'Логин: '.$user["name"];
echo
'E-mail: '.$user["mail"];

array query_fetch_all () – Получает массив результирующих рядов из SQL-запроса.

Пример:

// запрашиваем в базе данных всех пользователей
$users = DB::query_fetch_all("SELECT * FROM {users}");
foreach(
$users as $user)
{
    echo
'Имя: '.$user["fio"];
    echo
'Логин: '.$user["name"];
    echo
'E-mail: '.$user["mail"];
}

array query_range_fetch_all (string $query) – Отправляет запрос к базе данных с лимитом на количество получаюмых в результате рядов и получает массив результирующих рядов.

  • string $query: текст запроса

Пример:

// запрашиваем в базе данных 3 новости, начиная с 10й, не старше текущей даты
$rows = DB::query_range_fetch_all("SELECT id, [name], [anons] FROM {news} WHERE created<%d", time(), 10, 3);
foreach(
$rows as $row)
{
    echo
'ID: '.$row["id"];
    echo
'Название: '.$row["name"];
    echo
'Анонс: '.$row["anons"];
}

array query_fetch_key (string $query)

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

.

  • string $query: текст запроса

Пример:

// запрашиваем в базе данных новости не старше текущей даты
// результат получаем в виде массива, в котором ключами будет ID новости
$rows = DB::query_fetch_key("SELECT id, [name], [anons] FROM {news} WHERE created<%d", time(), "id");

echo
'Новость ID=4:';
    echo
'Название: '.$rows[4]["name"];
    echo
'Анонс: '.$rows[4]["anons"];

echo
'Новость ID=19:';
    echo
'Название: '.$rows[19]["name"];
    echo
'Анонс: '.$rows[19]["anons"];

array query_fetch_key_array (string $query) – Отправляет запрос к базе данных и получает массив, в котором ключами являются значения одного из полей, название которого переданно последним агрументом, а значениями массив результирующих рядов, соответствующих ключу..

  • string $query: текст запроса

Пример:

// запрашиваем комментарии за последние 10 дней
// с группировкой по комментарию-родителю
$comments = DB::query_fetch_key_array("SELECT * FROM {comments} WHERE created>%d", time() - 864000, "parent_id");
// комментарии первого уровня
forearch($comments[0] as $row)
{
    echo
$row["text"];
    
// вложенные комментарии второго уровня
    
if(! empty($comments[$row["id"]]))
    {
        foreach(
$comments[$row["id"]] as $r)
        {
            echo
$r["text"];
        }
    }
}

array query_fetch_key_value (string $query) – Отправляет запрос к базе данных и получает массив, в котором ключами являются значения одного из полей, название которого переданно предпоследним агрументом, а значениеями значения другого поля, название которого передано последним агрументом..

  • string $query: текст запроса

Пример:

// получаем категории товаров в виде массива,
// где ключами будут ID категории, а значениями название
$cats = DB::query_fetch_key_value("SELECT id, [name] FROM {shop_category} WHERE act='%d'", 1, "id", "name");
echo
'Название категории ID=3: '.$cats[3];
echo
'Название категории ID=5: '.$cats[5];

array query_fetch_value (string $query) – Отправляет запрос к базе данных и получает массив значений поля, название которого передано последним агрументом..

  • string $query: текст запроса

Пример:

// получаем массив идентификаторов активных пользователей
$user_ids = DB::query_fetch_value("SELECT id FROM {users} WHERE act='%d'", 1, "id");
print_r($user_ids);
/* выведет:
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
) */

mixed query_fetch_object () – Получает результирующий ряд как массив из SQL-запроса.

Пример:

// запрашиваем в базе данных пользователя ID=4
$user = DB::query_fetch_object("SELECT * FROM {users} WHERE id=4");
echo
'Имя: '.$user->fio;
echo
'Логин: '.$user->name;
echo
'E-mail: '.$user->mail;

string escape_string (string $str) – Мнемонизирует специальные символы в строке для использования в операторе SQL с учётом текущего набора символов/charset соединения.

  • string $str: исходная строка

Пример:

// подготовим данные, полученне от пользователя
// для безопасного использования непосредственно в SQL-запросе
$search = DB::escape_string($_GET["searchword"]);
DB::query("INSERT INTO {search_history} (created, name) VALUES (".time().", '".$search."')");

Ваши комментарии и дополнения

Не приведен формат для команды UPDATE - не помешало бы!
У нас стандартный SQL-синтаксис запросов. Можно, например, здесь посмотреть: http://phpclub.ru/mysql/doc/update.html
Синтаксис стандартный, за исключением способа передачи переменных в запрос, надо отметить.
То есть, запрос UPDATE будет выглядеть как-то так:
Пример:
DB::query("UPDATE {shop_category} SET [name]='%s', sort=%d WHERE id=%d", $_GET["name"], $_GET["sort"], $this->diafan->cat);
Меняем название текущей категории и номер сортировки в БД на значения переменных, переданных из адресной строки. Числовые значения допускается использовать без кавычек, а строковые значения должны быть в одиночных кавычках [name]='%s'

где квадратные скобки означают, что поле name мультиязычное, фигурные скобки прибавят к имени таблицы префикс таблиц БД из /config.php, а %d и %s - формат передаваемых из-за скобок переменных по порядку.
Я и имел ввиду, что создать запрос на основании стандартного синтаксиса не проблема. Запихиваешь его в DB::query() и вперед. Вопрос был именно в приведении примера как сделать UPDATE использую проверку устанавливаемых переменных в запросе.

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

Вот еще маленькое уточнение - а как будет выглядеть синтаксис при Update запросе меняющем значение НЕСКОЛЬКИХ полей - вот так?:

Код

DB::query("UPDATE {shop_category} SET [name]='%s' , [site_id]=%d WHERE id=%d", $_GET["name"], $new_site_id , $this->diafan->cat);

Или где то неверно. То есть интересует именно синтаксис записи значений переменных
Цитата
То есть интересует именно синтаксис записи значений переменных

Переменные в запросе используются по порядку. В каком порядке переменные по маске подставлялись в запросе, в том порядке их и нужно использовать за кавычками:
Пример:
DB::query("UPDATE {shop} SET f1='%s', f2=%d, f3='%s' WHERE f4=%d AND f5=%d", $p1, $p2, $p3, $p4, $p5 );
Отдельно стоит сказать о мультиязычности.
В Вашем примере Вы взяли поле [site_id] в квадратные скобки, что немного неправильно. Запрос, конечно, сработает, если в системе один язык, но в мультиязычности может выдать ошибку.
Квадратные скобки используются только для мультиязычного переводимого поля.

Объясню принцип: для основного языка в таблице поле имени называется name. А когда мы добавляем еще язык в систему, в таблице появляется еще одно поле рядом name1, чтобы пункт меню "О компании" в английской версии назывался "About". При этом поле site_id для всех языков остается неизменным. (посмотрите структуру БД для любой таблицы diafan.CMS с мультиязычными полями) Для третьего языка в системе появится name2. Если эти оба дополнительных языка удалить и снова создать еще один язык, будет поле name3. То есть цифра у поля - это id языка в системе.

diafan.CMS при выполнении запроса определяет какой язык текущий при выполнении запроса. Поэтому запрос UPDATE {shop_category} SET [name]='%s' в русском интерфейсе затронет поле name, а в другом языке поле name1.

Если не хотите путаться, лучше используйте точный запрос с конкретно указанным полем, т.е. все без квадратных скобок.
Ок, понял . Спасибо за доходчивые разъяснения. Надеюсь, что эти комментарии и пояснения помогут не только мне
Еще вопрос появился по удобному для применения запросу вот такого вида:
Код
INSERT INTO `diafan_shop` ( id , act1 )
VALUES ( 906997, '0' ) ON DUPLICATE
KEY UPDATE act1 ='0'


запрос упрощен до максимума для простоты восприятия

Как его записать с учетом синтаксиса проверки переменных?. Тут значение одной и то же переменной встречается в запросе дважды. Ее тип и значение надо также упоминать в запросе дважды ?
То есть как то так,? Или можно упростить?
Код

DB::query("INSERT INTO {shop} (id, [act] ) VALUES ( %d,'%d') ON DUPLICATE
KEY UPDATE [act] ='%d'", $id, '1','1');







DB::query("INSERT INTO {shop} (id, [act] ) VALUES ( %d,'%d') ON DUPLICATE
KEY UPDATE [act] ='%d'", $id,
'1',
'1');




А как получить количество рядов, затронутых последним INSERT, UPDATE, REPLACE или DELETE запросом?
Я, так понимаю, что надо дописать:

В includes/database.php
в класс DB метод
Код
public static function affected_rows()
{
return self::$backend->affected_rows();
}


в интерфейс DB_interface
Код
public function affected_rows();


В includes/database/database.mysqli.php добавить метод
Код
public function affected_rows()
{
return $this->connection->affected_rows;
}


В includes/database/database.mysql.php добавить метод
Код
public function affected_rows()
{
return mysql_affected_rows($this->connection);
}


Так?
Не знаю, на какой ответ я рассчитываю
Андрей, если функция нужна, то мы ее добавим в DIAFAN.CMS. Я добавила в пожелания Ваш код. В другой раз лучше сразу туда пишите, так как комментарии к документации все таки нужны для помощи пользователям. А в данном случае такую функцию лучше внести сразу в пакет DIAFAN.CMS, чем каждый раз добавлять в свой проект. Ну или в крайнем случае в дополнения такой функционал в виде файлов database.custom.php, database.mysql.custom.php и т. д.

(P.S. Извиняюсь, за обращение не по тому имени)
Ok! Спасибо, в следующий раз так и сделаю (просто уже начал писать вопрос, а потом соорудил код, который проверил и сразу же вставил, извините).

Конечно, мне показалось, что надо сразу иметь такую функцию в API, но пока ее нет любой заглянувший сюда, получит помощь в виде этого кода.

Ну, и в качестве еще небольшой помощи:
Версии Diafan, начиная с которых в API появились следующие функции
5.3.2
DB::query_fetch_all
DB::query_range_fetch_all
5.4.0.0
DB::query_fetch_key
DB::query_fetch_key_array
DB::query_fetch_key_value
DB::query_fetch_value
DB::query_fetch_object
5.4.6.10
DB::affected_rows

Удаленные функции начиная с версии Diafan 5.4.0.0
DB::title
DB::where
DB::last_id

P.S. И я не Сергей
Как быть когда нужно использовать регулярные выражения в запросе?
Пример запроса:
$sql = "SELECT * FROM `diafan_shop` where `name1` RLIKE \'[[:<:]]шкаф[[:>:]]\'";

Как мне использовать квадратные скобки, а?
В результате запроса «SELECT [name] FROM …» вы получите запись, с полем «name». А вот запрос вида «SELECT * FROM …» уже вернёт то же поле, но под именем, например, «name1».
Зарегистрируйтесь или авторизируйтесь для того, чтобы оставить комментарий.