Основы WordPress: взаимодействие с базой данных (часть 1)

В WordPress существует огромное количество различных функций, предназначенных для взаимодействия с базой данных. Несмотря на их удобство, они не являются единственно возможным решением. В данной статье мы рассмотрим простой и безопасный способ взаимодействия с базой данных, который основан на использовании класса $wpdb. Класс $wpdb, базирующийся на великолепном классе ezsql, автором которого является Джастин Винсент, позволяет выполнить запрос к любой таблице базы данных, а также помогает произвести обработку возвращенных данных. Поскольку класс является частью базовой функциональности WordPress, пользователям не нужно открывать отдельное соединение с базой данных (в данном случае вам понадобилось бы копировать фрагмент кода), и отпадает потребность в создании хаков, таких как изменение итогового набора после выполнения запроса.

В данной статье я покажу вам, как начать работу с классом $wpdb, как получить данные из БД WordPress и как выполнить более сложные запросы, которые позволяют обновить или удалить что-либо в базе данных. Методы, рассмотренные далее, позволяют обойти некоторые ограничения, выставляемые различными функциями, такими как get_posts() и wp_list_categories(). Вы сможете адаптировать запросы под свои собственные потребности, поднять производительность своего сайта, получая только те данные, которые действительно необходимы.

Если вы знаете, как функционирует MySQL или другие похожие языки, то никаких проблем при работе с классом $wpdb у вас не возникнет; вам понадобится лишь запомнить небольшое количество функций. Основное использование класса становится понятным на примере. Давайте создадим запрос к базе данных, позволяющий получить идентификаторы и заголовки четырех последних записей в порядке убывания числа комментариев.

<?php
   $posts = $wpdb->get_results("SELECT ID, post_title FROM $wpdb->posts WHERE post_status = 'publish'
   AND post_type='post' ORDER BY comment_count DESC LIMIT 0,4")
?> 

Как вы успели заметить, здесь приведен SQL-запрос, обернутый в PHP-код. Класс $wpdb содержит метод (методы — это специальное название для функций, являющихся внутренними для классов) под названием get_results(), который не только отправляет результаты работы, но и помещает их в удобный объект. Вы, возможно, заметили, что вместо wp_posts я использовал $wpdb->posts для получения доступа к базовым таблицам WordPress. Я еще вернусь к этому в дальнейшем.

Объект $results содержит полученные данные в следующем формате:

Array
(
   [0] => stdClass Object
      (
         [ID] => 6
         [post_title] => The Male Angler Fish Gets Completely Screwed
      )

   [1] => stdClass Object
      (
         [ID] => 25
         [post_title] => 10 Truly Amazing Icon Sets From Germany
      )

   [2] => stdClass Object
      (
         [ID] => 37
         [post_title] => Elderberry Is Awesome
      )

   [3] => stdClass Object
      (
         [ID] => 60
         [post_title] => Gathering Resources and Inspiration With Evernote
      )

)

Получение результатов из базы данных

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

get_results()

Функция, с которой мы уже успели столкнуться ранее. Позволяет преобразовать данные в массив, который содержит отдельные объекты в каждой строке:

<?php
   $posts = $wpdb->get_results("SELECT ID, post_title FROM wp_posts WHERE post_status = 'future'
   AND post_type='post' ORDER BY post_date ASC LIMIT 0,4")

   // Echo the title of the first scheduled post
   echo $posts[0]->post_title;
?> 

get_row

Когда вам требуется найти одну определенную строку в базе данных (к примеру, запись с наибольшим числом комментариев), вы можете использовать функцию get_row(). Она представляет искомые данные в виде одномерного объекта.

<?php
   $posts = $wpdb->get_row("SELECT ID, post_title FROM wp_posts WHERE post_status = 'publish'
   AND post_type='post' ORDER BY comment_count DESC LIMIT 0,1")

   // Echo the title of the most commented post
   echo $posts->post_title;
?>  

get_col

Метод очень похож на get_row, за единственным исключением: он получает отдельный столбец. Это действие полезно в том случае, если вы нуждаетесь в идентификаторах для 10 самых комментируемых записей. Как и get_row, функция get_col хранит результаты в одномерном объекте.

<?php
   $posts = $wpdb->get_col("SELECT ID FROM wp_posts WHERE post_status = 'publish'
   AND post_type='post' ORDER BY comment_count DESC LIMIT 0,10")

   // Echo the ID of the 4th most commented post
   echo $posts[3]->ID;
?>

get_var

В большинстве случаев вы будете нуждаться только в одном значении из базы данных; к примеру, вам может понадобиться электронная почта одного из пользователей. В этой ситуации вы можете использовать функцию get_var, позволяющую получить единственное значение. Тип данных для полученного значения не будет отличаться от типа данных этого же значения, хранящегося в БД (целые числа останутся целыми числами, строки останутся строками).

<?php
   $email = $wpdb->get_var("SELECT user_email FROM wp_users WHERE user_login = 'danielpataki' ")

   // Echo the user's email address
   echo $email;
?>  

Вставка в базу данных

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

$wpdb->insert( $table, $data, $format);

Этот метод получает три аргумента. Первый аргумент определяет название таблицы, в которую вы вставляете данные. Второй аргумент — массив, который содержит столбцы и соответствующие им значения, хранящиеся в виде пар «key-value» («ключ-значение»). Третий аргумент определяет тип данных для ваших значений в том порядке, в котором вы задали их. Пример:

<?php
   $wpdb->insert($wpdb->usermeta, array("user_id" => 1, "meta_key" => "awesome_factor", "meta_value" => 10), array("%d", "%s", "%d"));

   // Equivalent to:
   // INSERT INTO wp_usermeta (user_id, meta_key, meta_value) VALUES (1, "awesome_factor", 10);
?>

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

Определение формата является дополнительным аргументом; по умолчанию все значения обрабатываются как строки. Несмотря на это хорошим тоном считается явное указание формата. Вы можете использовать три значения: %s для строк, %d для десятичных чисел и %f для чисел с плавающей запятой.

Обновление данных

Для обновления данных используется метод под названием update(). Он аналогичен методу, рассмотренному выше, за тем лишь исключением, что нам понадобится обработать логическую цепь нашего обновления, которая задана в переменной where; для этой цели мы воспользуемся двумя дополнительными параметрами.

Переменные $table, $data и $format остались прежними. В переменной $where содержатся условия обновления, которые представляют собой массив, заданный в форме column-value (столбец-значение). Если вы определили несколько параметров, все они должны быть связаны друг с другом с помощью логического AND. Переменная $where_format во многом подобна $format: она определяет формат значений, хранящихся в переменной $where.

$wpdb->update( $wpdb->posts, array("post_title" => "Modified Post Title"), array("ID" => 5), array("%s"), array("%d") );    

Другие запросы

Хелперы, приведенные выше, позволяют справиться лишь с простыми задачами. Как быть с более сложными запросами? Если вам необходимо выполнить обновление с комплексным условием where, содержащим многократную логику AND/OR, вы не сможете использовать метод update(). Если вы хотите сделать что-либо наподобие удаления строки или задания набора символов, вам понадобится прибегнуть к помощи «общего» метода query(), который позволяет выполнить любой тип запросов.

$wpdb->query("DELETE FROM wp_usermeta WHERE meta_key = 'first_login' OR meta_key = 'security_key' ");    

Защита и валидация данных

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

Чтобы избежать SQL-инъекций, необходимо провести экранирование спецсимволов. В том случае, если вы используете хелперы, вам не понадобится ничего делать — все уже будет сделано за вас. Однако в случае с методом query() вам понадобится ставить защиту вручную с помощью метода prepare():

$sql = $wpdb->prepare( 'query' [, value_parameter, value_parameter ... ] );    

Чтобы сделать код более удобоваримым, давайте немного изменим основной формат:

$sql = $wpdb->prepare( "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value ) VALUES ( %d, %s, %d )", 3342, 'post_views', 2290 )
$wpdb->query($sql);

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

http://wp.smashingmagazine.com/2011/09/21/interacting-with-the-wordpress-database/

Блог про WordPress
Комментарии: 10
  1. HotIce

    (методы – это специальное название для функций, которые являются внутренними классами) — может функциями являющимися внутренними ДЛЯ класса? Или я что-то не так понимаю в ООП..

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

    1. Дмитрий (автор)

      Насчет первого я еще уточню, скорее всего ты прав.

      Экранирование — это так, для общего развития. Хелперы — это вспомогательные функции, в русском языке нет более подходящего слова для них. Я в одной из прошлых статей уже упоминал про них. Надо будет добавить и в глоссарий. Хелпер — по сути, обычная минималистичная функция, выполняющая конкретное действие и больше ничего не умеющая, что-то а-ля бритвы Оккама, только в контексте программирования.

  2. HotIce

    Спасибо за разъяснения. Интуитивно я понимаю, что такое хелперы, но лучше услышать подтверждение от тех, кто в этом разбирается лучше. Примитив в рамках контекста, я так понял. Сенкс.

    1. Дмитрий (автор)

      Вот, кстати, примитив — хороший синоним для них :)

  3. Dzmitry Samoila

    Spasibo vam bolshoe, a na etix umnikov ne obraschaite vnimaniya, kak pravilo nichego tolkogo oni v jizni ne sozdaut)

  4. Илья

    Статья полезная, спасибо! Но хотелось бы еще по подробнее узнать про вставку записей в БД, а точнее про название ячеек, что они значат и что в них писать. Чтоб уже полноценная статья была вставлена.

  5. Дмитрий

    Эх, все передирают статью с ошибками :) Запись в базу, пример в статье:
    $wpdb->insert($wpdb->usermeta, array(«user_id» => 1, «meta_key» => «awesome_factor», «meta_value» => 10), array(«%d», %s», «%d»));

    Здесь %s надо обособить в кавычки с обоих сторон, иначе ошибка будет.

    1. Дмитрий (автор)

      Спасибо, верное замечание)

  6. Андрей

    Здравствуйте. Подскажите как подсчитать количество постов с условием фильтра категория и метка. Нужно именно с помощью $wpdb, чтобы сократить количество запросов.

  7. Елена

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

Добавить комментарий для Дмитрий Отменить ответ

Получать новые комментарии по электронной почте.