WordPress как на ладони
Плагин рекламы для WordPress wordpress jino

wpdb{} WP 0.71

Позволяет производить любые операции с базой данных WordPress: вставлять, обновлять, получать или удалять данные.

WordPress предоставляет возможность удобно манипулировать своей базой данных за счет php класса wpdb.

php класс - относится к ООП (объектно-ориентированному программированию) и в традиционном своем понимании представляет собой полностью самодостаточный код, который должен выполнять определенную функцию. Например, в этом случае через класс wpdb мы может производить всевозможные операции с Базой Данных WordPress зная всего несколько "рычагов" управления классом, которые называются методами. Если говорить условно, то методы - это обычные php функции, только внутри класса.

Обращаться к методам класса wpdb нужно обязательно через глобальную переменную $wpdb (это экземпляр класса wpdb). Также нужно помнить, что внутри обычных функций нужно обязательно глобализировать $wpdb, иначе она будет простой переменной внутри функции, делается это так:

global $wpdb;

C помощью методов $wpdb можно управлять произвольными таблицами в Базе Данных, не обязательно только теми, которые были созданы WordPress. Например, у нас, среди прочих таблиц WP, есть таблица "newtable" и нам нужно выбрать все поля id из нее. Реализовать это можно таким SQL запросом используя $wpdb:

$newtable = $wpdb->get_results( "SELECT id FROM newtable" );
Создание своего подключения к базе данных

Нужно понимать, что один объект класса wpdb{} работает с одной БД - с текущей базой данных WordPress. Если нужно работать параллельно с какой-либо другой БД, то нужно создать еще один объект класса wpdb с указанием новых параметров соединения, отличных от тех что указаны в wp-config.php. Делается это так:

global $wpdb2;

$wpdb2 = new wpdb( 'имя_пользователя БД', 'пароль БД', 'название БД', 'localhost' );

// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if( ! empty($wpdb2->error) ) wp_die( $wpdb2->error );

// Готово, теперь используем функции класса wpdb
$results = $wpdb2->get_results("SELECT * FROM table");

Для сложных соединений с несколькими БД (репликами), есть хороший плаглин, который рекомендуют разработчики WP - hyperdb. Этот плагин расширяет возможности базового класса wpdb. Устанавливается он не как обычный плагин и требует определенных знаний работы с базами данных (в противном случае, толку от этого плагина не будет).

А теперь, перейдем к разбору класса wpdb.

Хуки из класса:
Возвращает

Экземпляр класса.

query - произвольный запрос к Базе Данных WordPress

Позволяет выполнять любые запросы к базе данных WordPress. В общем случае, она подразумевает выполнение не SELECT запросов, хотя и они могут также выполняться (но для них существуют $wpdb->get_results и другие функции см. ниже).

Возвращает

Число/false. Вернет количество строк, которые были задействованы в результате запроса (удалены/изменены/выбраны). Если запрос вызвал ошибку, то будет возвращено значение false.

$wpdb->query('query');
query(строка)
Запрос который нужно выполнить.

Имейте ввиду, что как и для всех функций класса wpdb, передаваемые параметры нужно очистить от SQL инъекций, сделать это можно двумя способами:  esc_sql($user_entered_data_string) или $wpdb->prepare(  'query' , value_parameter[, value_parameter ... ] ). Подробнее читайте в секции "Защита запросов от SQL инъекций". см. ниже.

Примеры

#1. Удалить произвольное поле 'gargle' и его значение у поста 13

$wpdb->query("DELETE FROM $wpdb->postmeta WHERE post_id = '13' AND meta_key = 'gargle'");

#2. Установить родительскую страницу 7 для страницы 15

$wpdb->query("
	UPDATE $wpdb->posts SET post_parent = 7
	WHERE ID = 15 AND post_status = 'static'");
к началу

get_var - получение определенной ячейки таблицы

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

Чтобы получить значение второй ячейки из второй строки результата, используйте второй и третий параметры: $column_offset = 1, $row_offset = 1.

Возвращает

Значение колонки: число, строку, дату и т.д.

  • Если запрос получает значение одной колонки, то функция вернет это значение (без всяких массивов).
  • Если запрос получает одну строку и несколько колонок, то функция вернет значение первой колонки (ячейки).
  • Если запрос получает несколько строк и колонок, то вернется значение первой строки первой колонки.
  • Вернет NULL, если результата нет.
$wpdb->get_var('query', $column_offset, $row_offset );
query(строка)
Запрос который нужно выполнить. Можно установить этот параметр в значение null, тогда функция вернет результат последнего запроса, который был выполнен классом (сохранился в переменной).
column_offset(число)
Нужная колонка (отступ по колонкам). по умолчанию 0 - первая колонка.
row_offset(число)
Нужная строка (отступ по строкам). по умолчанию 0 - первая строка.

Примеры

#1. Выведем на экран количество пользователей

$user_count = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $wpdb->users;"));
echo '<p>Количество пользователей равно: ' . $user_count . '</p>';

#2. Выведем на экран количество определенных произвольных полей

// определяем произвольный ключ, который нужно посчитать
$meta_key = 'miles';
$allmiles=$wpdb->get_var($wpdb->prepare("SELECT sum(meta_value) FROM $wpdb->postmeta WHERE meta_key = %s", $meta_key));
echo '<p>Общее количество произвольных полей miles: '.$allmiles . '</p>';

#3. Набор выводов статистики блога

### Общее Количество авторов блога
function get_totalauthors() {
	global $wpdb;
	$totalauthors = intval($wpdb->get_var("SELECT COUNT(ID) FROM $wpdb->users LEFT JOIN $wpdb->usermeta ON $wpdb->usermeta.user_id = $wpdb->users.ID WHERE $wpdb->users.user_activation_key = '' AND $wpdb->usermeta.meta_key = '".$wpdb->prefix."user_level' AND (meta_value+0.00) > 1"));

	return $totalauthors;
}

### Общее Количество постов
function get_totalposts() {
	global $wpdb;
	$totalposts = intval($wpdb->get_var("SELECT COUNT(ID) FROM $wpdb->posts WHERE post_type = 'post' AND post_status = 'publish'"));

	return $totalposts;
}

### Общее Количество страниц
function get_totalpages() {
	global $wpdb;
	$totalpages = intval($wpdb->get_var("SELECT COUNT(ID) FROM $wpdb->posts WHERE post_type = 'page' AND post_status = 'publish'"));

	return $totalpages;
}

### Общее Количество комментариев
function get_totalcomments() {
	global $wpdb;
	$totalcomments = intval($wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = '1'"));

	return $totalcomments;
}

### Общее Количество комментаторов
function get_totalcommentposters() {
	global $wpdb;
	$totalcommentposters = intval($wpdb->get_var("SELECT COUNT(DISTINCT comment_author) FROM $wpdb->comments WHERE comment_approved = '1' AND comment_type = ''"));

	return $totalcommentposters;
}

### Общее Количество ссылок
function get_totallinks() {
	global $wpdb;
	$totallinks = intval($wpdb->get_var("SELECT COUNT(link_id) FROM $wpdb->links"));

	return $totallinks;
}
к началу

get_row - выбор строки таблицы

Получает одну строку таблицы в виде объекта. Если результат запроса содержит больше одной строки, то функция получит только первую строку результата. Чтобы получить вторую строку из запроса, укажите параметр $row_offset = 1.

Возвращает

Объект/массив/null. Вернет null, если не удалось получить данные.

$wpdb->get_row('query', $output_type, $row_offset);
query(строка)
Запрос который нужно выполнить.
output_type
Одна из трех констант. по умолчанию OBJECT. Может быть:
OBJECT - результат будет возвращен в виде объекта.
ARRAY_A - результат будет возвращен в виде ассоциативного массива.
ARRAY_N - результат будет возвращен в виде пронумерованного массива.
row_offset(число)
Номер возвращаемой строки результата запроса. 0 - это первая строка (установлено по умолчанию)

Примеры

#1. Получим всю информацию о ссылке 10

$mylink = $wpdb->get_row("SELECT * FROM $wpdb->links WHERE link_id = 10");

// Теперь, свойства (переменные) $mylink - это названия
//колонок из таблицы $wpdb->links со значениями полей таблицы:
echo $mylink->link_id; // выведет на экран "10"

#2. С использованием константы:

$mylink = $wpdb->get_row("SELECT * FROM $wpdb->links WHERE link_id = 10", ARRAY_A);

// результатом будет ассоциативный массив
echo $mylink['link_id']; // выведет на экран "10"

или

$mylink = $wpdb->get_row("SELECT * FROM $wpdb->links WHERE link_id = 10", ARRAY_N);
// результатом будет пронумерованный массив
echo $mylink[1]; // выведет на экран"10"
к началу

get_col - выбор столбца таблицы

Функция выбирает данные целой колонки таблицы и возвращает их в виде одномерного массива.

Если запрос вернул больше чем одну колонку (столбец), то функция вернет только данные первого столбца, остальное можно будет получить из переменной last_result. Можно указать отступ в $column_offset, чтобы получить данные не первого столбца, а, например, второго: $column_offset = 1.

Возвращает

Массив с данными запроса.  Пустой массив, если не удалось получить данные.

$wpdb->get_col( $query, $column_offset );
$query(строка)
Запрос который нужно выполнить. Можно установить этот параметр в значение null, тогда функция вернет результат последнего запроса, который был произведен.
$column_offset(число)
Флаг указывающий какую колонку возвращать. По умолчанию 0 (первая колонка).

Примеры

#1. Выбор столбца из результатов запроса

Для этого примера представим, что у нас блог об автомобилях. Каждый пост описывает какой-либо автомобиль (например, Ford Mustang 1969 года). Для каждого поста предусмотрено по 3 произвольных поля: manufacturer (производитель), model(модель) и year(год выпуска). Этот пример выведет на экран заголовки постов, отфильтрованных по производителю (ford) и отсортированных по модели и году.

get_col здесь используется для того, чтобы получить массив ID всех записей, удовлетворяющих определенным критериям и отсортированных в нужном порядке. Затем через цикл foreach мы выводим заголовки по имеющимся у нас ID:

<?php
$meta_key1 = 'model';
$meta_key2 = 'year';
$meta_key3 = 'manufacturer';
$meta_key3_value = 'Ford';

$postids = $wpdb->get_col($wpdb->prepare("
SELECT      key3.post_id
FROM        $wpdb->postmeta key3
INNER JOIN  $wpdb->postmeta key1
			on key1.post_id = key3.post_id
			and key1.meta_key = %s
INNER JOIN  $wpdb->postmeta key2
			on key2.post_id = key3.post_id
			and key2.meta_key = %s
WHERE       key3.meta_key = %s
			and key3.meta_value = %s
ORDER BY    key1.meta_value, key2.meta_value",$meta_key1, $meta_key2, $meta_key3, $meta_key3_value)); 

if ($postids) {
  echo 'List of ' . $meta_key3_value . '(s), sorted by ' . $meta_key1 . ', ' . $meta_key2;
  foreach( $postids as $id ){
	$post = get_post(intval($id));
	setup_postdata($post);
	?>
	<p><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></p>
	<?php
  }
}

#2. Список постов которые имеют определенное произвольное поле (Color), но отсортированы они по значению другого произвольного поля (Display_Order).

$meta_key1 = 'Color';
$meta_key2 = 'Display_Order';

$postids = $wpdb->get_col($wpdb->prepare("
SELECT      key1.post_id
FROM        $wpdb->postmeta key1
INNER JOIN  $wpdb->postmeta key2
			on key2.post_id = key1.post_id
			and key2.meta_key = %s
WHERE       key1.meta_key = %s
ORDER BY    key2.meta_value+(0) ASC",
		 $meta_key2,$meta_key1)); 

if ($postids) {
  echo 'List of '. $meta_key1  . ' posts, sorted by ' . $meta_key2 ;
  foreach ($postids as $id) {
	$post=get_post(intval($id));
	setup_postdata($post);?>
	<p><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></p>
	<?php
  }
}
к началу

get_results - выборка комбинированных результатов

Различные данные из нескольких строк таблицы могут быть получены при использовании метода get_results. Функция возвращает результат запроса в массиве, каждый элемент которого представляет собой результат функции get_row, т.е. в каждом элементе массива находятся все запрашиваемые данные одной строки.

Возвращает

Массив/объект/null.

  • Результат запроса в виде массива объектов (OBJECT, OBJECT_K), массива массивов (ARRAY_A, ARRAY_N).
  • Вернет пустой массив: array() — когда строк по запросу не найдено или ошибка запроса.
  • Вернет NULL — когда запрос пустая строка или передан неправильный тип вывода ($output_type).
$wpdb->get_results('query', output_type);
query(строка)
Запрос который нужно выполнить. Можно установить этот параметр в значение null, тогда функция вернет результат последнего запроса, который был произведен.
output_type(строка)

Флаг указывающий как нужно вернуть данные. По умолчанию OBJECT. есть 4 варианта:

  • OBJECT - вернет массив объектов с числовыми ключами - элементы массива будут объекты полученных данных.
  • OBJECT_K - похож на предыдущий, только в индексах главного массива будут значения первой колонки результата запроса. При этом обратите внимание, что если в индекс будут попадать одинаковые значения, то данные будут стирать друг друга...
  • ARRAY_A - вернет нумерованный двумерный массив, каждый вложенный элемент которого будет ассоциативным массивом, в котором ключом будет название колонки.
  • ARRAY_N - вернет нумерованный двумерный массив, каждый вложенный элемент которого будет так же нумерованным массивом.

Примеры

#1. Получим ID и заголовки черновиков, ID автора которых равен 5 и выведем на экран заголовки постов.

$fivesdrafts = $wpdb->get_results("SELECT ID, post_title FROM $wpdb->posts
	WHERE post_status = 'draft' AND post_author = 5");

foreach ($fivesdrafts as $fivesdraft) {
	echo $fivesdraft->post_title;
}

#2. Выведем на экран ссылки на черновики автора с ID = 5

<?php
$fivesdrafts = $wpdb->get_results("SELECT * FROM $wpdb->posts
	WHERE post_status = 'draft' AND post_author = 5");
if ($fivesdrafts) :
	foreach ($fivesdrafts as $post) :
		setup_postdata($post);
?>
	<h2><a href="<?php the_permalink(); ?>" rel="bookmark"
		title="Permanent Link to <?php the_title(); ?>"><?php the_title(); ?></a></h2>
<?php
	endforeach;
else :
?>
	<h2> Не найдено</h2>
<?php endif; ?>

#3. Пример сложного запроса с GROUP BY (отзывов в WooCommerce)

/**
* Возвращает результаты рейтинга (отзывов в WooCommerce) сгрупированный по оценкам
* 
* @param int $post_id идентификатор поста
* 
* @return array массив объектов, где каждый объект - сгрупированные данные по одной из оценок
*/
function get_cnt_rating_reviews_one_product($post_id){
	global $wpdb;

	return $wpdb->get_results(
		$wpdb->prepare("
			SELECT COUNT(meta.meta_id) as num, meta.meta_value
			FROM $wpdb->comments as comments
			INNER JOIN $wpdb->commentmeta as meta ON comments.comment_ID = meta.comment_id
			WHERE comments.comment_post_ID = %d AND meta_key = 'rating'
			GROUP BY meta.meta_value;
		",
		$post_id )
	);

}

// использование
get_cnt_rating_reviews_one_product( 4350 );
к началу

insert - вставка новой записи (строки) в таблицу

Вставляет указанные данные в указанную таблицу.

$wpdb->insert() включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']...

Возвращает

true/false.
true — при успешной записи данных;
false — если данные не были вставлены в таблицу.

После добавления данных созданное значение AUTO_INCREMENT можно получить в переменной: $wpdb->insert_id

$wpdb->insert( $table, $data, $format );
table(строка)
название таблицы в которую будем вставлять данные.
data(строка)
Данные которые нужно вставить ('колонка куда вставлять' => 'что вставлять').
format(строка)
Формат данных который будет ассоциирован с указанными значениями в параметре $data. Если не указать, то для всех значений $data будет указан формат строки. Возможные форматы данных: %s - строка; %d - целое число и %f - дробное число. При указании формата, WordPress переводит переданные данные в указанный формат перед тем, как сохранить данные в базу данных.

Примеры

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

$wpdb->insert(
	'table',
	array( 'column1' => 'value1', 'column2' => 123 ),
	array( '%s', '%d' )
)
к началу

update - обновление записи (строки) в таблице

Возвращает

Число (кол-во обраб. строк), 0 или false.

  • число - сколько строк было обработано
  • 0 - запрос был выполнен корректно, но ни одна строка не была обработана.
  • false - запрос провалился или ошибка запроса.

Так как возвращается 0, если никакие поля не были обновлены (изменены), но запрос был выполнен корректно, проверку результата запроса на ошибку нужно делать с учетом типа возвращаемых данных $res === false.

$wpdb->update() включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']...

$wpdb->update( $table, $data, $where, $format = null, $where_format = null );
table(строка)
название таблицы которую нужно обновить.
data(массив)
данные которые нужно обновить ('название колонки' => 'новое значение').
where(массив)
Ассоциированный массив с условием для замены (WHERE) ( 'название колонки' => 'чему равно').
format(массив/строка)
Формат данных который будет ассоциирован с указанными значениями в параметре $data.
where_format(массив/строка)
Формат данных который будет ассоциирован с указанными значениями в параметре $where. Возможные значения формата: %s - строка; %d - любое число; %f - FLOAT число. Если не указать формат, то все значения в WHERE будут обработаны как строки.

Примеры

#1. Обновим строку ID которой равен 1

Значение первой колонки строка, значение второй колонки число:

$wpdb->update( 'table',
	array( 'column1' => 'value1', 'column2' => $_GET['val'] ),
	array( 'ID' => 1 )
);

#2. Тоже самое с указанием типов передаваемых данных

$wpdb->update( 'table',
	array( 'column1' => 'value1', 'column2' => $_GET['val'] ),
	array( 'ID' => 1 ),
	array( '%s', '%d' ),
	array( '%d' )
);
к началу

delete - удаление строки из таблицы

Удаляет строки из таблицы по переданному в параметр $where условию.

$wpdb->delete() включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']...

Возвращает

Число/false. Число удаленных строк или false.

$wpdb->delete( $table, $where, $where_format = null );
$table(строка) (обязательный)
Название таблицы.
$where(массив) (обязательный)
Массив условий, по которым будут выбираться строки для удаления. Например:
array('id' => 25, 'title' => 'книги') удалит строку с полями  id=25 и title=книги.
$where_format(строка/массив)
Формат данных который будет ассоциирован с указанными значениями в параметре $where. Возможные значения формата: %s - строка; %d - любое число; %f - FLOAT число. Если не указать формат, то все значения в WHERE будут обработаны как строки.
По умолчанию:  null

Примеры

// Удалим строку с полем ID=1 из таблицы table
$wpdb->delete( 'table', array( 'ID' => 1 ) );

// Укажем формат значения $where
$wpdb->delete( 'table', array( 'ID' => '1' ), array( '%d' ) ); // 1 будет обработано как число (%d)...
к началу

prepare - защита запроса от SQL инъекций

В SQL есть такое понятие как "внедрение в запрос SQL кода", сделать это можно когда в запрос передаются динамические данные. Например, в запрос передаются значение input полей формы, тогда в поле формы можно указать данные, которые в итоге станут частью SQL запроса. Так можно внедриться в запрос и что-нибудь испортить или просто нарушить код самого запроса. Выглядит это примерно так:

SELECT * FROM table WHERE id = '$var'
// если $var будет равно например "2' AND id = (DROP TABLE table2)"
// то у получиться
SELECT * FROM table WHERE id = '2' AND id = (DROP TABLE table2)'

Таким образом можно внедриться в сам запрос и изменить его.

Чтобы этого не произошло запросы с передаваемыми в них переменными нужно обрабатывать методом wpdb::prepare():

$sql = $wpdb->prepare( 'query' [ parameter1, parameter2 ... ] );
query(строка)

Запрос. В нем можно использовать заменители:

  • %d - число
  • %s - строка
  • %f - дробное число (число с плавающей точкой, с версии 3.3).

Использование знака % в любых других случаях может вызывать ошибку, поэтому его нужно претворять еще одним %. Например, чтобы использовать команду LIKE %вхождение%, её нужно записать так: LIKE %%вхождение%%.

Также можно указывать все холдеры из функции sprintf(). Но делать это надо аккуратно. Например, это может быть удобно тут:

$wpdb->prepare('SELECT * FROM table WHERE field = %1$d OR field2 = %1$d', 2 );
//> SELECT * FROM table WHERE field = 2 OR field2 = 2

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

$wpdb->prepare('SELECT * FROM table WHERE field = "%1$s" OR field2 = "%1$s"', '"str' );
//> SELECT * FROM table WHERE field = "\"str" OR field2 = "\"str"
parameter(строка/массив)
Переменные, которые относятся к заменителям. Считаются слева на право. Переменные можно указать через запятую, как в php функции sprintf() или во втором параметре можно передать массив для замены.

Заметка: с версии WP 3.5 wpdb::prepare() обязательно должны быть переданы минимум 2 параметра: запрос и значение переменной, иначе появится php ошибка.

esc_sql()

Кроме метода $wpdb->prepare(), который предпочтительнее, потому что исправляет некоторые ошибки форматирования, запрос можно очистить функцией esc_sql().

$name   = esc_sql( $name );
$status = esc_sql( $status );

$wpdb->get_var( "SELECT something FROM table WHERE foo = '$name' and status = '$status'" );

Обратите внимание что после esc_sql() очищенную строку можно использовать только внутри кавычек '' или "". Т.е. так писать нельзя: ORDER BY $value, где $value = esc_sql($value);

Примеры

#1. Добавим произвольное поле к посту 10:

$metakey = "'крах' БД";
$metavalue = "WordPress может 'сломать' Базу Данных если не экранировать запрос.";

$wpdb->query(
	$wpdb->prepare(
		"INSERT INTO $wpdb->postmeta ( post_id, meta_key, meta_value ) VALUES ( %d, %s, %s )",
		10,
		$metakey,
		$metavalue
  )
);

Как видно из примера, с prepare() нет необходимости заботиться об экранировании кавычек и прочего, что может навредить запросу.

#2. Такой же пример

Только тут все переменные передаются во втором параметре в виде массива:

$metakey = "'крах' БД";
$metavalue = "WordPress может 'сломать' Базу Данных если не экранировать запрос.";

$wpdb->query(
	$wpdb->prepare(
		"INSERT INTO $wpdb->postmeta ( post_id, meta_key, meta_value ) VALUES ( %d, %s, %s )",
		array(
		10, 
		$metakey, 
		$metavalue
	) 
  )
);

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

к началу

esc_like - очистка LIKE строки

Чтобы подготовить строку для использования в LIKE части SQL запроса, используйте $wpdb->esc_like( $text ):

global $wpdb;
$link = $wpdb->esc_like( $link ); // подготовим строку для LIKE аргумента
$link = esc_sql( $link );         // очистим переменную
$link = '%' . $link . '%';        // создадим полную переменную поиска LIKE

// найдем комментарии в тексте или ссылке автора, есть указанная ссылка
$spammy = $wpdb->query("SELECT comment_approved FROM $wpdb->comments 
	WHERE (comment_content LIKE '$link' OR comment_author_url LIKE '$link')
		AND comment_approved = 'spam' 
	LIMIT 1;"
);

Короткая запись с prepare()

global $wpdb;

$link = '%' . $wpdb->esc_like( $link ) . '%';

$comment = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_author_url LIKE %s LIMIT 1", $link ) );

Функция like_escape( $string ) запрещена с версии 4.0. Используйте вместо нее $wpdb->esc_like( $string )

(show/hide/print)_error - показать или спрятать ошибки SQL

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

$wpdb->show_errors(); // включит показ ошибок
$wpdb->hide_errors(); // выключит показ ошибок

Так же можно вывести на экран саму ошибку, если таковая имеется:

$wpdb->print_error();
к началу

get_col_info - получить информацию о колонке

Получает информацию о колонках последнего запроса. Функция вернет массив с информацией об определенных в запросе колонках. Если в запросе колонки не определены, то функция вернет информацию о всех колонках таблицы. Это может пригодится, когда был возвращен объект, о данных которого мы ничего не знаем.

Работает на основе кэша, поэтому сначала нужно запустить запрос с помощью get_resiults(), get_col(), get_var() и т.д. а потом вызвать wpdb::get_col_info() которая вернет данные колонок последнего запроса.

$wpdb->get_col_info( $type, $offset );
$type(строка)

В этом параметре указывается какую информацию нам нужно получить. По умолчанию: name. Вот список возможных вариантов:

  • name - название колонки.
  • table - название таблицы к которой принадлежит колонка.
  • max_length - максимальная длинна данных колонки
  • not_null - 1 если ячейка колонки не может принимать значение NULL
  • primary_key - 1 если колонка является первичным ключом
  • unique_key - 1 если ячейки колонки должны быть всегда уникальны
  • multiple_key - 1 если ячейки колонки могут быть не уникальны
  • numeric - 1 если колонка содержит числовые данные
  • blob - 1 если колонка содержит данные типа BLOB (двоичные данные)
  • type - тип колонки
  • unsigned - 1 если колонка имеет тип данных UNSIGNED
  • zerofill - 1 если колонка имеет тип данных ZEROFILL

По умолчанию: name

$offset(число)

Указатель, информацию о какой колонке нужно получить:

  • Если указать -1, то будут получена информация о всех колонках в виде массива. По умолчанию.

  • Если указать 0 или больше то будет возвращена информация об указанной колонке, где 0 - первая колонка, 1 - вторая и т.д.
    По умолчанию: -1

Примеры

global $wpdb, $table_name;

$wpdb->show_errors(); // включим показ SQL ошибок

$results  = $wpdb->get_results("SELECT * FROM $table_name");
$cols_name = $wpdb->get_col_info('name');

echo 'Колонки таблицы `'. $table_name .'`:';
if( is_array($cols_name) ){
	foreach( $cols_name as $name )
		echo " $name";
}
else {
	echo 'Ошибка, нет данных: ';
	$wpdb->print_error();
}

$wpdb->hide_errors(); // выключим показ SQL ошибок
к началу

flush - сброс кэша

Можно сбросить последние сохраненные данные в свойствах класса:

$wpdb->flush();

Эта команда очистит следующие свойства (переменные): $wpdb->last_result, $wpdb->last_query и $wpdb->col_info.

Свойства (переменные) класса

$show_errors
Показывать ошибки или нет, когда возвращается результат.
По умолчанию: Да (true)
$suppress_errors
Подавлять ли ошибки в процессе построения запроса.
$last_error
Последняя ошибка из любого запроса.
$num_queries
Количество запросов которые выполняются.
$num_rows
Количество строк возвращенных последним запросом.
$rows_affected
Сохраняет число задействованных строк из последнего запроса
$insert_id
Идентификатор (ID) сгенерированный последним запросом, для SQL параметра AUTO_INCREMENT
$last_query
Последний запрос, который был выполнен классом.
$last_result
Результат последнего запроса.
$func_call
Текстовое описание последнего вызова query/get_row/get_var
$queries
Можно сохранить все запросы которые были сделаны к БД и их время выполнения, для этого нужно определить константу SAVEQUERIES как TRUE (например в config.php). По умолчанию она выключена (false). После того как эта константа включена в эту переменную будут собираться все запросы в виде массива данных.
$col_info
Информация о колонках последнего запроса.
$prefix
Префикс таблиц БД определенный для WordPress. Может пригодиться для мульти-сайтов.
$base_prefix
Префикс базовой таблицы WordPress. В мультисайте для сайтов сети префик отличается. Тут храниться префикс таблиц основного сайта сети.
$ready
Логический. Готов ли класс к выполнению запросов.
$blogid
Идентификатор текущего блога.
$siteid
ID сайта.
$tables
Список названий таблиц сайта (без префикса).
$global_tables
Глобальные таблицы: 'users', 'usermeta'
$ms_global_tables
Глобальные таблицы в режиме MU: 'blogs', 'signups', 'site', 'sitemeta', 'sitecategories', 'registration_log', 'blog_versions'
$collate
Режим сопоставления (сравнивания) данных в колонках базы данных.
к началу

Таблицы Базы Данных WordPress

Схема базы данных WordPress - структура всех таблиц

Подробное описание базы данных смотрите по этой ссылке: http://codex.wordpress.org/Database_Description

Записи

$wpdb->posts
Таблица куда записываются посты, постоянные страницы, произвольные типы записей, вложения и т.п.
$wpdb->postmeta
Таблица с записями о произвольных полях.
Мета поля для таблицы $wpdb->postmeta.

Пользователи

$wpdb->users
Таблица с данными о зарегистрированных пользователях (индексные данные).
$wpdb->usermeta
Дополнительная информация о пользователях, такая как Имя, Ник, права и прочее.
Мета поля для таблицы $wpdb->users.

Комментарии

$wpdb->comments
Таблица с записями комментариев.
$wpdb->commentmeta
Мета поля для таблицы $wpdb->comments.

Таксономии

$wpdb->terms
Таблица содержащая в себе информацию о названии категорий, меток, категорий ссылок и других таксономий.
$wpdb->termmeta
Таблица содержащая в себе дополнительные поля для таблицы $wpdb->terms.
$wpdb->term_taxonomy
Таблица с информацией о различных таксономиях их описание.
$wpdb->term_relationships
Таблица связывающая таксономии с контентом (постами, записями и т.п.)

Остальное

$wpdb->links
Таблица с записями ссылок.
$wpdb->options
Таблица опций (настроек).

Таблицы в MU (Multisite) сборке

$wpdb->blogs
Все сайты подсети.
$wpdb->blog_versions
Содержит текущую версию базы данных каждого сайта. Данные обновляются при обновлении БД для каждого сайта сети.
$wpdb->registration_log
Содержит данные администраторов сайтов, которые создаются при создании сайтов.
$wpdb->signups
Содержит пользователей, которые были зарегистрированы через базовую регистрацию WordPress со страницы: Администрация > Супер Админ > Настройки.
$wpdb->site
Содержит, адреса основных сайтов.
$wpdb->sitemeta
Данные сайтов: различные опции, включая администратора сайта.
$wpdb->users
Список пользователей всех сайтов сети. Это общая таблица пользователей для всей сети. Это привычная таблица, только в мультисайт версии добавляются еще 2 поля: spam и delete.
$wpdb->usermeta
Содержит мета-данные пользователей. Настройки пользователя для разных сайтов сети отличаются префиксом в индексе ключа. Например роли хранятся в таких метаполях: wp_capabilities, wp_1_capabilities, wp_2_capabilities ...
Базовые таблицы каждого сайта сети
Таблицы сайта сети: wp_posts, wp_options и т.д.. Для каждого сайта сети создаются одинаковые таблицы, но с разным префиксом, например: wp_options, wp_1_options, wp_2_options ...

Код wpdb: wp-includes/wp-db.php WP 4.8

Код слишком большой, смотрите его на отдельной странице...

Cвязанные функции

Из раздела: Классы

wpdb 130 комментариев
Полезные 9 Вопросы 3 Все
  • Спасибо за детальную инструкцию. Есть вопрос по соединениям. Если у меня плагин в цикле открывает 200 соединений и будет запускаться раз в 10 минут, то не будет ли это накапливать незакрытые соединения с БД? Вопрос: нужно ли как то закрывать соединение с БД в конце отработки плагина?

    • Kama4396

      Точно не знаю, кажется не нужно.

      1
    • campusboy1579 cайт: wp-plus.ru
      @

      После отработки php плагина база сама закрывает соединения, разве не так? В коде wpdb есть только соединения с базой, разъединения не увидел, потому что не зачем скорее всего.

      1
  • campusboy1579 cайт: wp-plus.ru
    @

    Почему-то в секции про delete стоит заметка об update

    1
  • Антон

    у меня возникла проблема.
    у меня есть ajax обработчик который добавляет запись в бд когда пользователь выставляет оценку записи, он сначала пытается обновить запись через update если не выходит то тогда он вставляет новую запись через метод insert. Но если очень быстро кликать на рейтинг и отправлять часто ajax запросы то он иногда метод как-то не правильно срабатывает и возвращает 0, возникает ощущение что если при обновлении записи, передаваемые значения такие-же как есть уже в бд, то он считает что запись не была изменена, получается что нужно использовать запрос по типу "SELECT COUNT(id) FROM $table WHERE userid=%d AND postid=%d" и смотреть если такая запись уже есть то обновлять ее, а если нету то создавать новую.

    вот привожу сам ajax обработчик который у меня имеется сейчас

    $user = wp_get_current_user();
    			if (!$user->exists()){
    				echo json_encode(['message'=>'вы не авторизованы!', 'success' => false]);
    				wp_die();
    				return;
    			}
    			$postid = intval($_POST['postid']);
    			$rate = min(max(intval($_POST['rate']),0), 5);
    			$userid = $user->ID;
    			global $wpdb;
    			$table = $wpdb->get_blog_prefix() . 'rates';
    			$update = $wpdb->update($table, ['postid' => $postid, 'rating' => $rate, 'userid' => $userid], ['postid' => $postid, 'userid' => $userid], ['%d', '%d', '%d'], ['%d', '%d']);
    			if ($update == 0) {
    				$insert = $wpdb->insert($table, ['postid' => $postid, 'rating' => $rate, 'userid' => $userid], ['%d', '%d', '%d']);
    				if ($insert){
    					$avg_rate = $this->get_avg_post_rate($postid);
    					update_post_meta($postid, 'rating', $postid);
    					echo json_encode(['message'=>'Оценка добавлена', 'rate' => $avg_rate, 'success' => true, 'update' => $update]);
    					wp_die();
    					return;
    				} else {
    					echo json_encode(['message'=>'Оценка не добавлена', 'success' => false]);
    					wp_die();
    					return;
    				}
    			} else {
    				$avg_rate = $this->get_avg_post_rate($postid);
    				update_post_meta($postid, 'rating', $postid);
    				echo json_encode(['message'=>'Оценка обновлена', 'rate' => $avg_rate, 'success' => true]);
    				wp_die();
    				return;
    			}
    			echo json_encode(['message'=>'произошла ошибка', 'success' => false]);
    			wp_die();
    			return;
    1
    • Антон

      Да, я был прав метод update действительно возвращает число затронутых строк только в том случае если значение в них реально изменилось, возможно так работает сама субд, но суть в том что этот метод не всегда подходит для проверки существования записи, стоит это иметь в виду, хотя лучше было бы если бы он менял значение даже если оно совпадает с имеющимся, так сказать строго выполнял то что ему "говорят", даже если это не совсем логично, но в общем вот исправленный рабочий код

                  $user = wp_get_current_user();
      			if (!$user->exists()){
      				echo json_encode(['message'=>'вы не авторизованы!', 'success' => false]);
      				wp_die();
      				return;
      			}
      
      			$postid = intval($_POST['postid']);
      			$rate = min(max(intval($_POST['rate']),0), 5);
      			$userid = $user->ID;
      
      			global $wpdb;
      			$table = $wpdb->get_blog_prefix() . 'rates';
      			$exist = $wpdb->get_var($wpdb->prepare("SELECT COUNT(id) FROM $table WHERE postid=%d AND userid=%d", [$postid, $userid]));
      
      			if ($exist == 0) {
      				$insert = $wpdb->insert($table, ['postid' => $postid, 'rating' => $rate, 'userid' => $userid], ['%d', '%d', '%d']);
      				if ($insert){
      					$avg_rate = $this->get_avg_post_rate($postid);
      					update_post_meta($postid, 'rating', $postid);
      					echo json_encode(['message'=>'Оценка добавлена', 'rate' => $avg_rate, 'success' => true]);
      					wp_die();
      					return;
      				} else {
      					echo json_encode(['message'=>'Оценка не добавлена', 'success' => false]);
      					wp_die();
      					return;
      				}
      			} else {
      				$update = $wpdb->update($table, ['postid' => $postid, 'rating' => $rate, 'userid' => $userid], ['postid' => $postid, 'userid' => $userid], ['%d', '%d', '%d'], ['%d', '%d']);
      				if ($update === false){
      					echo json_encode(['message'=>'Не удалось обновить оценку', 'success' => false]);
      					wp_die();
      					return;
      				} else {
      					$avg_rate = $this->get_avg_post_rate($postid);
      					update_post_meta($postid, 'rating', $postid);
      					echo json_encode(['message'=>'Оценка обновлена', 'rate' => $avg_rate, 'success' => true]);
      					wp_die();
      					return;
      				}
      			}
      			echo json_encode(['message'=>'Произошла неизвестная ошибка', 'success' => false]);
      			wp_die();
      			return;
      1
  • Юрий

    Добрый день!

    При работе одного из скрипта часто выходит ошибка и сервер зависает с переполнением памяти:

    PHP Warning: Missing argument 2 for wpdb:repare(), called in /var/www/mysites/data/www/site.ru/wp-content/plugins/folding-category-widget/focal_wp28.php on line 768 and defined in /var/www/mysites/data/www/site.ru/wp-includes/wp-db.php on line 1246

    Ссылка ведет на строку:

    $querystr = $wpdb->prepare($querystr);

    Вот часть кода с строчкой:

        {
    		global $wpdb;
    		$post_count = 0;
    
    		$children = get_categories('child_of=' . $category);
    		$children[] = get_category($category);
    		$subcatposts = array();
    
    		foreach ($children as $cat) {
    			$querystr = "
    			SELECT DISTINCT $wpdb->posts.ID
    			FROM $wpdb->term_taxonomy, $wpdb->posts, $wpdb->term_relationships
    			WHERE $wpdb->posts.ID = $wpdb->term_relationships.object_id
    			AND $wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id
    			AND $wpdb->term_taxonomy.term_id = $cat->term_id
    			AND $wpdb->posts.post_status = 'publish'
    			AND $wpdb->posts.post_type = 'post'
    			AND $wpdb->posts.post_date < NOW()
    		";
    			$querystr = $wpdb->prepare($querystr);
    			$result = $wpdb->get_results($querystr, ARRAY_A);
    
    			if ($result)
    				foreach ($result as $id)
    					$subcatposts[] = $id["ID"];
    		}
    
    		$subcatpostsu = array_unique($subcatposts);
    		return array(count($subcatposts), count($subcatpostsu));
    	}

    Помогите пожалуйста как правильно оптимизировать эту строку?
    Как понимаю это связано из-за того, что нет двух переменных, но вот как исправить это я не понимаю sad

    • Kama4396

      Переполнение памяти и ошибка показанная тут - разные вещи... Тут тебе нужно указать второй аргумент в $wpdb->prepare - читай доки про эту функцию... Тут она неправильно используется...

      Запрос странный, где JOIN? И вообще, это базовый запрос по рубрике и дате для него лучше использовать WP_Query или get_posts(), тогда ВП сам построит грамотный SQL запрос и не надо руками объединять таблицы, к тому же кажется не очень правильно...

      • Юрий

        Ок спасибо.
        А почему не связано с переполнением?
        Просто когда память заполняется то в логах выходит только эта ошибка...

        • Юрий

          Подскажите, по строчке, так будет правильно?

          $querystr = $wpdb->prepare($querystr, 'publish', 'post');
          • Kama4396

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

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

  • Александр

    В get_results:
    "Флаг указывающий как нужно вернуть данные. По умолчанию OBJECT. есть 4 варианта:
    OBJECT - вернет двумерный пронумерованный массив, каждый вложенный элемент которого представлен в виде объекта данных."
    Выше указано (и примеры это подтверждают): "Результат запроса в виде массива объектов (OBJECT, OBJECT_K)"
    Массив объектов считается же одномерным, разве нет? Двумерный это массив массивов. Заранее извеняюсь, если чего не понял - в терминологии еще не спец

  • Александр

    Вам спасибо за ваш труд.
    Вопрос по статье - очистка от sql-инекций, разумеется, вызовет изменение передаваемых данных. Как потом их восстановить в первозданном виде? Поясню: с помощью insert помещаю в таблицу данные, среди которых html-код. Этот код содержит адреса ссылок, заключенные в двойные кавычки. При вставке все двойные кавычки экранируются. Когда получим эти данные обратно и вставим этот html-код на страницу, ни одна из ссылок (а также картинок и т.д.) корректно работать не будет. Как быть?

    • Kama4396

      Экранированная кавычка становится символом "кавычка" а не частью SQL запроса. Т.е. при экранировании в БД записывается просто кавычка без \. Либо у вас проблема не в том, либо её нет, а вы думаете наперед неправильно...

      • Александр

        В textarea набрал код
        <a href="www.google.ru"><img src="<?php echo SIMPLE_PATH; ?>images/cat.jpg"></a>
        Вставил в БД insert-ом. В БД выглядело так:
        <a href=\"www.google.ru\"><img src=\"<?php echo SIMPLE_PATH; ?>images/cat.jpg\"></a>

        • Kama4396

          При post запросе сервер экранирует строки... В результате в inset попадает то что получается в БД... Перед вставкой в insert обработай строку через wp_unslash()

  • Александр

    $wpdb->delete( $table, $where, $where_format = null );
    Как указывать условие удаления строк, если в параметре $where нужно указать промежуток значений (например от 3 до 7 ).... ?

    Ответить4 месяца назад #
  • Александр

    Вот такой вопрос: как в 'where' сделать несколько возможных значений? В php это
    WHERE param in (value1, value2, ..., valueN)
    Здесь такая вещь поддерживается? А то как это реализовать через массив, не представляю

    Ответить4 месяца назад #
    • Александр

      Сначала отправил, потом увидел, что тезка выше похожее спрашивал. Да, жаль что не поддерживается

      Ответить4 месяца назад #
    • campusboy1579 cайт: wp-plus.ru
      @

      Здесь обычные SQL запросы. Если SQL поддерживает IN, значит тут соответственно тоже. Если у вас массив, то переделать его в строку можно легко с помощью php функции implode и подставить в IN полученный результат.

      Ответить4 месяца назад #
      • Александр

        Так и сделал. Только join проще запомнить - в JS есть аналог

        Ответить4 месяца назад #
  • @

    Здравствуйте! С помощью get_col_info можно проверить отдельную ячейку?
    Например есть запрос

    $check_image = $lwpdb->get_var("SELECT photo_blob FROM tovar WHERE group_tov_id = '16' AND tovar_id='$id'")or wp_die( $lwpdb->error );
    Ответить4 месяца назад #
    • Kama4396

      А что проверить нужно? get_col_info дает данные о самой колонке, а не о значении ячейки... вы не путайте... она оч редко нужна...

      Ответить3 месяца назад #
  • Сергей

    Всем добра! Нужна помощь. Написал для теста такую функцию, она должна по мета ключу вернуть метазначение, но возвращает пустой массив. Если делаю выборку по meta_id выбирает без проблем, по meta_key вообще не выбирает...

    function get_meta_value($meta_key){
    	global $wpdb;
    	$metas = $wpdb->get_results("
    		SELECT meta_value 
    		FROM". $wpdb->postmeta ." 
    		WHERE meta_key = ".$meta_key, 'ARRAY_A');
    }
    Ответить3 месяца назад #
    • Kama4396

      Неправильный запрос... Во первых он не безопасный, во-вторых там строка и её нужно в кавычки совать ''

      function get_meta_value( $meta_key ){
      	global $wpdb;
      	$sql = $wpdb->prepare("SELECT meta_value FROM $wpdb->postmeta WHERE meta_key = %s", $meta_key );
      	$metas = $wpdb->get_results( $sql, ARRAY_A );
      	return $metas;
      }
      Ответить3 месяца назад #

Здравствуйте, !

Ваш комментарий