Запрос SQL для перечисления всех публикаций определенного типа с определенным набором значений мета данных публикаций в виде столбца.

Вопрос или проблема

Я хочу, чтобы все записи типа ‘ajde_events’ были в виде строк, каждая с колонкой для некоторых базовых данных из таблицы постов и некоторых (не всех) связанных значений postmeta. Я заимствовал следующее из этого поста Как отображать несколько ключей/значений поста meta_key/meta_values с помощью SQL-запроса, но, как отмечает автор в комментарии, он возвращает только одну строку (которая, по-видимому, является строкой, где местоположение – это строка, начинающаяся с “Z”, что, я подозреваю, является “Наивысшей” или максимальной строкой).

SELECT p.ID, p.post_title,
MAX(IF(PM.meta_key = 'evcal_location', PM.meta_value, NULL)) AS location,
MAX(IF(PM.meta_key = 'evcal_srow', PM.meta_value, NULL)) AS start_time
FROM wp_posts AS p
LEFT JOIN wp_postmeta AS pm ON p.ID = pm.post_id
WHERE post_type="ajde_events" AND post_status="publish"
ORDER BY p.ID

Как мне получить строку для каждого соответствующего поста?

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

В плагине вы можете использовать что-то вроде:

<?php
// Получить все опубликованные CPT
$allEvents = get_posts(array(
    'post_type' => 'ajde_events',
    'post_status' => 'publish',
    'numberposts' => -1
));
// Если были найдены какие-либо
if($allEvents) {
    // Открыть/создать ваш csv (ваш код здесь)
    // Перебор всех CPT и получение postmeta
    foreach($allEvents as $event) {
        $meta = get_post_meta($event);
        // Сохранить postmeta с объектом поста
        $event->evcal_location = $meta['evcal_location'];
        $event->evcal_srow = $meta['evcal_srow'];
        // Добавить полный объект поста с postmeta в массив
        $fullData[] = $event;
    }
    // Сбросить запрос
    wp_reset_postdata();
    // Сохранить в csv и закрыть его (ваш код здесь)
}
?>

Куда поместить этот код, зависит от того, как вы хотите, чтобы плагин работал. Возможно, вы захотите создать экран администратора, где пользователь может вручную нажать кнопку для загрузки CSV, или, возможно, вы хотите настроить cron-задачу, которая автоматически создаёт его каждый день и отправляет файл по электронной почте.

Запрос, который я опубликовал, просто нуждается в изменении предложения ORDER BY на GROUP BY, и он будет делать то, что я хотел.

Ответ или решение

Для получения всех постов с типом "ajde_events" и специфическими значениями метаданных в столбцах необходимо выполнить SQL-запрос, который правильно группирует данные. Исходный вопрос касается проблемы, связанной с возвращением только одной строки вместо всех подходящих. Рассмотрим, как это исправить и как данное решение встраивается в более общий контекст работы с базами данных в WordPress.

Теория

В WordPress структура хранения данных базируется на двух ключевых таблицах: wp_posts, которая содержит основную информацию о постах, и wp_postmeta, где хранятся дополнительные данные. Для извлечения необходимых данных требуется корректное использование SQL-запроса с учетом специфики объединения (JOIN) и группировки (GROUP BY).

SQL-запросы обычно включают в себя условия JOIN для соединения данных из разных таблиц и условия WHERE для фильтрации данных по определенным критериям. Обычно, для извлечения нескольких строк с различными значениями метаданных используется функция агрегирования, такая как MAX(), чтобы преобразовать несколько строк в одну, однако, это может привести к возврату только одной строки, если объединение и группировка не настроены корректно.

Пример

Изначально было предложено использовать следующую основную структуру SQL-запроса:

SELECT p.ID, p.post_title,
MAX(IF(pm.meta_key = 'evcal_location', pm.meta_value, NULL)) AS location,
MAX(IF(pm.meta_key = 'evcal_srow', pm.meta_value, NULL)) AS start_time
FROM wp_posts AS p
LEFT JOIN wp_postmeta AS pm ON p.ID = pm.post_id
WHERE p.post_type = 'ajde_events' AND p.post_status = 'publish'
ORDER BY p.ID

Эта структура не учитывала необходимость группировки по идентификатору поста, что приводило к неожиданному результату. Чтобы исправить это, нужно заменить выражение ORDER BY на GROUP BY:

SELECT p.ID, p.post_title,
MAX(IF(pm.meta_key = 'evcal_location', pm.meta_value, NULL)) AS location,
MAX(IF(pm.meta_key = 'evcal_srow', pm.meta_value, NULL)) AS start_time
FROM wp_posts AS p
LEFT JOIN wp_postmeta AS pm ON p.ID = pm.post_id
WHERE p.post_type = 'ajde_events' AND p.post_status = 'publish'
GROUP BY p.ID

Добавление GROUP BY p.ID обеспечивает правильную группировку данных по каждому отдельному посту, что даёт возможность извлечь и отобразить все соответствующие строки.

Применение

Работа с базами данных в WordPress предполагает не только возможность осуществлять SQL-запросы напрямую, но и предпочтение использовать встроенные WordPress-функции для безопасности и производительности. Решение предложенной задачи можно также реализовать на PHP, используя API WordPress, как это показано в следующем примере:

<?php
// Полная выборка всех опубликованных "ajde_events"
$allEvents = get_posts(array(
    'post_type' => 'ajde_events',
    'post_status' => 'publish',
    'numberposts' => -1
));

if ($allEvents) {
    // Код для работы с CSV здесь
    foreach ($allEvents as $event) {
        $meta = get_post_meta($event->ID);
        $event->evcal_location = isset($meta['evcal_location']) ? $meta['evcal_location'][0] : '';
        $event->evcal_srow = isset($meta['evcal_srow']) ? $meta['evcal_srow'][0] : '';
        $fullData[] = $event;
    }
    // Завершение манипуляций с данными
    wp_reset_postdata();
    // Закрытие и сохранение CSV (ваш код здесь)
}
?>

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

Заключение

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

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

Капча загружается...