$wpdb выберите все метаданные для каждого поста

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

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

SELECT wp_posts.post_title, wp_posts.post_date,
    wp_posts.ID, wp_postmeta.post_id, wp_postmeta.meta_key
    FROM wp_postmeta
    INNER JOIN wp_posts
    ON wp_postmeta.post_id=wp_posts.id
    WHERE wp_posts.post_status="publish"
    LIMIT 5

И это возвращает следующее:

Массив
(
    [0] => stdClass Объект
        (
            [post_title] => Привет, мир!
            [post_date] => 2015-11-11 08:44:54
            [ID] => 1
            [post_id] => 1
            [meta_key] => _edit_lock
        )

    [1] => stdClass Объект
        (
            [post_title] => Главная
            [post_date] => 2015-11-11 08:44:54
            [ID] => 2
            [post_id] => 2
            [meta_key] => _wp_page_template
        )

    [2] => stdClass Объект
        (
            [post_title] => Главная
            [post_date] => 2015-11-11 08:44:54
            [ID] => 2
            [post_id] => 2
            [meta_key] => _edit_last
        )
...

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

Массив
(
    [0] => stdClass Объект
        (
            [post_title] => Привет, мир!
            [post_date] => 2015-11-11 08:44:54
            [ID] => 1
            [post_id] => 1
            [meta] => массив(
                '_wp_page_template' => 'home.php',
                '_edit_last' => 2015-11-11 08:44:54,
            )
        )

    [1] => stdClass Объект
        (
            [post_title] => Главная
            [post_date] => 2015-11-11 08:44:54
            [ID] => 2
            [post_id] => 2
            [meta] => массив(
                '_wp_page_template' => 'home.php',
                '_edit_last' => 2015-11-11 08:44:54,
            )
        )

    [2] => stdClass Объект
        (
            [post_title] => О нас
            [post_date] => 2015-11-11 08:44:54
            [ID] => 3
            [post_id] => 3
            [meta] => массив(
                '_wp_page_template' => 'home.php',
                '_edit_last' => 2015-11-11 08:44:54,
            )
        )

Это действительно просто.

get_post_meta($postid);

Это вернет все значения примерно в том же синтаксисе.

В более рабочем цикле:

<?php
    $custom = new WP_Query(array("posts_per_page" => -1))
    if( $custom->have_posts() ) {
        while ( $custom->have_posts() ) {
            the_post();
            $data = get_post_meta(get_the_ID());
        }
    } else {
        /* Записей не найдено */
    }
?>

Для всех, кто наткнется на это.. Я решил эту задачу, сделав следующее:

(адаптировано под ваш код)

SELECT wp_posts.post_title, wp_posts.post_date,
wp_posts.ID, wp_postmeta.post_id, wp_postmeta.meta_key, 
GROUP_CONCAT(wp_postmeta.meta_key SEPARATOR ':') AS meta_keys

FROM wp_postmeta
INNER JOIN wp_posts
ON wp_postmeta.post_id=wp_posts.id
WHERE wp_posts.post_status="publish"
GROUP BY wp_postmeta.post_id
LIMIT 5

Сделав GROUP_CONCAT(wp_postmeta.meta_key SEPARATOR ':') AS meta_keys и GROUP BY wp_postmeta.post_id, создается результат meta_keys, по которому вы затем в PHP можете разделить по :

$meta_keys = explode(':', $item->meta_keys);

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

Чтобы извлечь все метаданные, связанные с каждой публикацией в WordPress, вам необходимо оптимизировать ваш SQL-запрос и применять определенные техники для обработки этих данных. Давайте разберемся поэтапно.

Постановка задачи

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

Начальный запрос

Вот ваш исходный запрос:

SELECT wp_posts.post_title, wp_posts.post_date,
    wp_posts.ID, wp_postmeta.post_id, wp_postmeta.meta_key
FROM wp_postmeta
INNER JOIN wp_posts
ON wp_postmeta.post_id=wp_posts.ID
WHERE wp_posts.post_status="publish"
LIMIT 5

Оптимизация запроса

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

SELECT wp_posts.post_title, wp_posts.post_date,
    wp_posts.ID, 
    GROUP_CONCAT(CONCAT(wp_postmeta.meta_key, ':', wp_postmeta.meta_value) SEPARATOR ',') AS meta_data
FROM wp_postmeta
INNER JOIN wp_posts
ON wp_postmeta.post_id = wp_posts.ID
WHERE wp_posts.post_status = "publish"
GROUP BY wp_posts.ID
LIMIT 5

Объяснение запроса

  1. GROUP_CONCAT(): Эта функция объединяет значения в одну строку, отделяя их запятой. Каждый элемент имеет формат meta_key:meta_value, что упрощает дальнейшую обработку.

  2. GROUP BY: Благодаря группировке по wp_posts.ID, вы гарантируете, что для каждой публикации будет возвращена только одна строка с её заголовком, датой и метаданными.

Использование данных в PHP

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

$results = $wpdb->get_results($sql);

foreach ($results as $item) {
    $meta_data_pairs = explode(',', $item->meta_data);
    $meta = [];

    foreach ($meta_data_pairs as $pair) {
        list($key, $value) = explode(':', $pair);
        $meta[$key] = $value;
    }

    $post_info = [
        'post_title' => $item->post_title,
        'post_date' => $item->post_date,
        'ID' => $item->ID,
        'meta' => $meta,
    ];

    // Теперь $post_info содержит нужные данные
    print_r($post_info);
}

Заключение

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

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

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

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