Основы WordPress: взаимодействие с базой данных (часть 2)
Помимо рассмотренных в прошлой статье прекрасных методов существует множество других переменных и функций, упрощающих жизнь любому веб-разработчику. Я остановлюсь лишь на некоторых из них, наиболее распространенных и востребованных; в случае острой необходимости остальные функции можно будет получить из Codex’а.
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.
Такая конструкция используется в результате того, что пользователь может самостоятельно определять префикс для таблиц. Несмотря на то что большинство людей остаются верными стандартному префиксу 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 "); // When run, because show_errors() is set, the error message will tell you that the "post_id" field is an unknown // field in this table (since the correct field is ID)
Создание простого отслеживания с помощью $wpdb
Если вы обладаете поверхностными практическими умениями, эта глава предназначена для вас. Давайте в качестве примера работы с $wpdb возьмем простой отслеживающий плагин, написанный мною для своего веб-сайта.
Чтобы сохранить простоту изложения, я не буду описывать каждую деталь плагина. Я рассмотрю лишь структуру базы данных и некоторые запросы к ней.
Структура таблиц
Чтобы отследить все щелчки по рекламным объявлениям, а также их просмотры, я создал таблицу; давайте назовем ее “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 был получен от безопасного источника. Я предлагаю экранировать ваши данные вне зависимости от обстоятельств. Хакеры – превосходные программисты. Они могут перехитрить вас такими способами, о которых вы не подозреваете. К тому же, я и сам могу повредить свои же сайты сильнее, чем любой хакер, поэтому меры предосторожности я произвожу и для себя.
Обновление результатов
Мы храним наши рекламные объявления как произвольные типы данных; чтобы облегчить создание статистических отчетов, мы сохраняем также общее количество щелчков, совершенных по объявлениям. Мы могли бы сложить все щелчки в нашей базе данных, так что давайте посмотрим, что необходимо сделать в первую очередь.
$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(), но я его упущу, чтобы не усложнять пример
Заключительные мысли и советы
Я надеюсь, что вы поняли, как работать с классом $wpdb и теперь сможете применять его для решения различных задач. Ниже приведены заключительные подсказки и советы, которые помогут эффективно использовать этот уникальный класс.
Я призываю вас быть осторожными: большая мощь всегда подразумевает под собой большую ответственность. Удостоверьтесь в том, что вы выполнили экранирование своих данных и проверил их валидацию. Неправильное использование класса – основная причина взлома веб-сайтов.
Запрашивайте только те данные, в которых вы нуждаетесь. Если вы будете выводить на экран заголовок статьи, нет никакой необходимости в получении всех данных из каждой строки. В данной ситуации вам понадобится только заголовок и ID:
SELECT title, ID FROM wp_posts ORDER BY post_date DESC LIMIT 0,5.
Несмотря на то что вы всегда можете прибегнуть к помощи метода query(), рекомендуется по возможности останавливать свой выбор на хелперах (insert, update, get_row, etc.). Они являются примитивными кирпичиками, позволяющими создавать простые запросы. К тому же хелперы автоматически экранируют данные, что делает их использование безопасным.
Внимательно подходите к удалению записей из базы данных WordPress. Когда в WordPress удаляется любой комментарий, происходит огромное количество действий: число комментариев в таблице wp_posts уменьшается на единицу, удаляются все данные в таблице comment_meta и т.д. При удалении убедитесь в том, что вы очистили все лишнее.
Чтобы использовать богатый потенциал класса, изучайте официальную документацию. Я также рекомендую обратить свое внимание на класс ezSQL, котрый можно использовать в своих проектах, не связанных с WordPress; я применяю его практически во всех своих разработках.
http://wp.smashingmagazine.com/2011/09/21/interacting-with-the-wordpress-database/