Работаем с базой данных в WordPress. Основы работы с базой данных в WordPress, с помощью класса wpdb

Важнейшие основы WordPress: взаимодействие с базой данных

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

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

Класс $wpdb моделирует и автоматизирует множество заданий, связанных с базой данных WordPress..

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

Начинаем работать с базой данных в WordPress

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

<?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
      )

)

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

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

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(), но вместо захвата отдельной строки результатов он берет отдельную колонку. Это полезно, если вам хотелось бы вернуть ID только 10 самых комментируемых постов. Как и get_row(), он хранит результаты в одномерном объекте.

<?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;
?>

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

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

$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"));

   // Эквивалентно:
   // INSERT INTO wp_usermeta (user_id, meta_key, meta_value) VALUES (1, "awesome_factor", 10);
?>

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

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

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

К данному моменту вы уже не удивитесь, когда услышите, что для обновления данных у нас также есть метод-ассистент  с очень сильным названием update(). Его применение напоминает то, что мы видели выше; но для манипулирования выражением where нашего обновления нужны два дополнительных параметра.

$wpdb->update( $table, $data, $where, $format = null, $where_format = null );

Параметры $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' ");

Защита и валидация

Надеюсь, вам не нужно рассказывать о том, как важно убедиться, что ваши данные защищены и что вашей базой данных не смогут манипулировать! Валидация данных немного выходит за пределы этой статьи, но обязательно посмотрите когда-нибудь, что может сказать Кодекс WordPress о Валидации данных (Data Validation).

Вдобавок к валидации вам понадобится экранировать все запросы (escape). Даже если вы не знакомы с атаками 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);

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

Переменные класса и прочие методы

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

insert_id()

Каждый раз при вставке чего-либо в таблицу у вас там наверняка появится автоматически приращенный ID. Чтобы найти значение самой последней вставки, выполненной вашим скриптом, можно использовать $wpdb->insert_id.

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

   $meta_id = $wpdb->insert_id;

num_rows()

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

Названия таблиц

Все базовые названия таблиц хранятся в переменных, чьи названия в точности такие же, как их эквивалент основной таблицы. Название таблицы постов (возможно, wp_posts) будет храниться в переменной $posts, так что вы могли бы вывести ее с помощью $wpdb->posts.

Мы используем ее, потому что у нас есть возможность выбирать префикс для своих таблиц WordPress. В то время как большинство людей использует префикс по умолчанию wp, некоторые пользователи хотят или нуждаются в пользовательском префиксе. Во имя гибкости этот префикс жестко не кодируется, так что если вы пишете плагин и применяете в запросе wp_postmeta вместо $wpdb->postmeta, ваш код на некоторых вебсайтах не станет работать.

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

Управление сообщениями об ошибке

Вызывая методы show_errors() или hide_errors(), можно включать или выключать сообщения об ошибках (по умолчанию они выключены), чтобы получить больше информации о происходящем. В любом случае для распечатки ошибок последнего запроса вы также можете применять метод print_error().

$wpdb->show_errors();
   $wpdb->query("DELETE FROM wp_posts WHERE post_id = 554 ");

   // По причине того, что установлен show_errors(), при запуске сообщение об ошибках скажет вам, что поле "post_id" неизвестно
  // поле в этой таблице (так как правильное поле – это ID)

Построение простого отслеживания с применением знания $wpdb

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

Простоты ради я не стану описывать каждую деталь этого плагина. Просто покажу структуру базы данных и несколько запросов.

Структура нашей таблицы

Чтобы отследить щелчки и наведение мыши на рекламных объявлениях я создал таблицу; давайте назовем ее “tracking.” Эта таблица записывает действия пользователей в режиме реального времени. Каждое наведение и щелчок записывается в ее собственный ряд в следующей структуре/порядке:

ID
Автоматически приращенное ID.

time
Дату и время совершения действия.

deal_id
ID сделки, которое связано с действием (т.е. рекламный блок, на который щелкали или смотрели).

action
Вид действия (т.е. щелчок или наведение).

action_url
Страница, на которой инициировано действие.

user_id
ID пользователя, если он залогинен.

user_ip
IP пользователя для устранения любых злоумышленных намерений.

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

Вставка данных в таблицы

При щелчке пользователя на рекламное объявление он обнаруживается, а нужная нам информация посылается в скрипт в форме массива $_POST со следующими данными:

Array
(
   [deal_id] => 643
   [action] => click
   [action_url] => http://thisiswhereitwasclicked.com/about/
   [user_id] => 223
   [user_ip] = 123.234.223.12
)

Затем мы можем вставить эти данные в базу данных с помощью нашего метода-помощника, как здесь:

$wpdb->insert('tracking', array("deal_id" => 643, "action" => "click", "action_url" => "http://thisiswhereitwasclicked.com/about/",
"user_id" => 223, "user_ip" => "123.234.223.12"), array("%d", %s", "%s", "%d", "%s"));

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

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

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

Удаление действий с IP, внесенного в «черный список»

Если обнаруживается, что IP-адрес 168.211.23.43 очень-очень нехорошо себя ведет, мы можем внести его в «черный список». В таком случае при группировке ежедневных данных нам понадобится удалить все входы с этого IP.

$sql = $wpdb->prepare("DELETE FROM tracking WHERE user_ip = %s ", '168.211.23.43');
   $wpdb->query($sql);

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

Обновление итогов

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

$total = $wpdb->get_var("SELECT COUNT(ID) WHERE deal_id = 125 ");

Так как получить отдельную переменную легче, чем постоянно загружать себя более сложными запросами каждый раз при группировке данных, можно было бы хранить текущую сумму отдельно. Наши рекламные объявления хранятся как посты с пользовательским типом, так что логично держать эту сумму в таблице postmeta. Для хранения этих данных давайте применим мета-ключ total_clicks.

$wpdb->update( $wpdb->postmeta, array("meta_value" => $total), array("ID" => 125), array("%d"), array("%d") );
// обратите внимание, что это следует делать с помощью update_post_meta(), я сделал это данным образом ради примера

Финальные мысли и подсказки

Надеюсь, вы теперь лучше понимаете класс WordPress $wpdb и сможете применять его для улучшения своих проектов. В заключение вот вам несколько последних подсказок и приемов эффективного использования этого класса.

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

Запрашивайте только те данные, которые вам нужны. Если вы будете показывать название статьи, нет необходимости искать все данные из каждой строки. В таком случае просто запрашивайте название и ID: SELECT title, ID FROM wp_posts ORDER BY post_date DESC LIMIT 0,5.

В то время как можно применять метод query()для любого запроса, лучше, где возможно, использовать методы-ассистенты (insert, update,get_row и т.д.). Они более модульные и безопасные, потому что автоматически экранируют ваши данные.

Будьте осторожны при удалении записей из базы данных WordPress (или любой другой). Когда WordPress удаляет комментарий, также происходит множество других действий: нужно уменьшить на один подсчет комментариев в wp_poststable, все данные из таблицы comment_meta также нуждаются в удалении, и так далее. Убедитесь, что тщательно прибираете за собой, особенно при удалении чего-либо.

Почитайте в официальной документации обо всех переменных класса и прочие сведения. Это поможет вам использовать все возможности класса. Я также рекомендую прочесть об общем применении класса ezSQL в ваших не-WordPress проектах; я применяю его исключительно почти везде.

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

Автор: Daniel Pataki

Источник: http://wp.smashingmagazine.com/

Редакция: Команда webformyself.

Курс WordPress-Ученик

12 фишек без которых Вы гарантированно не создадите полноценный сайт на WordPress!

Смотреть курс

Метки: , ,

Комментарии Вконтакте:

Комментарии Facebook:

Комментарии (8)

  1. Елена

    Добрый день, может вопрос не по теме, ну я хочу откатить версию WordPress назад до 3.2? Как это сделать

    • Андрей Кудлай

      Здравствуйте, Елена. Скорее всего, откатить невозможно. Варианта в таком случае только один — сделать бэкап БД, удалить полностью WP, установить нужную версию и залить бэкап.

  2. Елена

    Спасибо)

  3. Гулзира

    Подскажите, пожалуйста, а как вернуть БД? нечаянно удалила папку с админкой

    • Андрей Кудлай

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

  4. Александр

    В виджете применяю функцию:
    Но она не работает. Сам запрос при вводе в phpMyadmin проходит и возвращает правильный результат.

  5. Дмитрий

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

  6. Елена

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

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree