Использование get_post_meta в WP_Query

26 мая 2014 г., 18:19:00
Просмотры: 13.5K
Голосов: 1

Я разрабатываю плагин для добавления лайков к записям

Хочу создать таблицу на странице плагина, которая будет показывать каждую запись и количество лайков

function my_plugin_options() {

    echo '<p>Таблица лайков</p>';
    echo '</div>';

    echo '<table>';
  echo '<tr>';
  echo '<td>Запись</td>';
  echo '<td>Количество лайков</td>';
  echo '</tr>';

    // -- WP_Query -- 

    $like_args = array(
        'post_type' => 'post',
        'order' => 'DES',
        'post_status' => 'publish'
    );

    $like_loop = new WP_Query($like_args);

    if($like_loop->have_posts()):
        while($like_loop->have_posts()):
            $like_loop->the_post();

    // -- WP_Query -- 


    $likes = get_post_meta( $like_loop->post_ID, "_like_amount", true);     

    echo '<tr>';
    echo '<td>';
    the_title();
    echo '</td>';
    echo '<td>';
    $likes;
    echo '</td>';
    echo '</tr>';

    endwhile;
    endif;

    wp_reset_postdata();

    echo '</table>';
}

У меня есть метаполе '_like_amount' в каждой записи, которое содержит количество лайков.

Как правильно использовать get_post_meta для получения метаполя в цикле WP_Query?

Я пробовал:

$likes = get_post_meta( $like_loop->post_ID, "_like_amount", true);

Но это не работает

3
Комментарии

Можешь перефразировать свой вопрос? Что именно не работает в твоем коде и что он должен делать? Очень сложно понять, о чем ты спрашиваешь. Ты говоришь "как использовать это в WP_Query", но использовать для чего конкретно?

Tom J Nowell Tom J Nowell
26 мая 2014 г. 22:40:23

Теперь все заработало после добавления global $post и использования $post->ID. Я обновил исходный код в посте.

user51590 user51590
26 мая 2014 г. 23:14:02

Можешь объяснить, в чем изначально была проблема, и опубликовать ответ как отдельный ответ (не редактируй исходный код в вопросе, чтобы исправить его)?

Tom J Nowell Tom J Nowell
27 мая 2014 г. 01:39:45
Все ответы на вопрос 3
1

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

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

function filter_query_add_likes( $clauses, WP_Query $wp_query ) {
    if ( !is_admin() && !$wp_query->is_main_query() ) {
        global $wpdb;

        # Добавляем нужное мета-значение как times_liked
        $clauses['fields'] .= ', IFNULL( meta_like.meta_value, 0 ) as times_liked ';

        # Присоединяем поле postmeta на основе ID записи и нужного ключа
        # - предполагается, что у каждой записи есть только одно значение times_liked!
        $clauses['join'] .= <<<SQL
 LEFT JOIN {$wpdb->prefix}postmeta AS meta_like ON meta_like.post_id = {$wpdb->prefix}posts.ID AND meta_like.meta_key = '_like_amount'
SQL;

    }
    return $clauses;
}

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

function my_plugin_options() {
    # То же самое, что и раньше, но с использованием heredoc
    echo <<<HTML
<p>Таблица лайков</p>
</div>
<table>
<tr>
    <td>Запись</td>
    <td>Количество лайков</td>
</tr>
HTML;


    $like_args = array(
        'post_type' => 'post',
        'order' => 'DES',
        'post_status' => 'publish'
    );
    # Устанавливаем новый фильтр для этого запроса
    add_filter('posts_clauses', 'filter_query_add_likes', 10, 2);

    $like_loop = new WP_Query( $like_args );

    # Удаляем фильтр, чтобы случайно не затронуть другие запросы
    remove_filter('posts_clauses', 'filter_query_add_likes', 10, 2);

    if ( $like_loop->have_posts() ) {
        while ( $like_loop->have_posts() ) {
            # Использование next_post упрощает доступ к записям
            $current_post = $like_loop->next_post();

            # Теперь times_liked (из фильтра) доступен без
            # необходимости выполнять дополнительный запрос с get_post_meta()
            $likes = $current_post->times_liked;
            # Заголовок можно получить напрямую, если нужно
            $title = $current_post->post_title;

            # Формируем строку таблицы
            echo <<<HTML
<tr>
    <td>{$title}</td>
    <td>{$likes}</td>
</tr>
HTML;

        }
    }

    # Завершаем таблицу
    echo "\r\n</table>";

}

Этот код делает следующее:

  • Теперь используется только один запрос для получения всех результатов, которые нужно отобразить
  • Легко получить любые данные из объекта записи, включая количество лайков
  • Если у записи еще нет счетчика лайков, он получит значение 0 благодаря вызову ISNULL при редактировании поля fields

В целом, это работает намного быстрее, чем использование get_post_meta(), особенно если вы работаете с большим количеством записей.

19 сент. 2015 г. 00:29:15
Комментарии

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

Privateer Privateer
19 сент. 2015 г. 00:36:54
1

После выполнения $like_loop->the_post() глобальная переменная $post устанавливается в текущую запись в цикле, поэтому вам нужно:

$likes = get_post_meta( $post->ID, "_like_amount", true); 

Или...

$likes = get_post_meta( get_the_ID(), "_like_amount", true); 

... что в некоторых случаях является более надежным вариантом.

Однако, я не понимаю, что вы имеете в виду под "Как использовать это мета-поле в моем WP_Query". Предоставленный вами код имеет мало общего с WP_Query, и если вы хотите включить это значение в аргументы запроса, вы не объясняете, по каким условиям хотите выполнять запрос.

26 мая 2014 г. 18:29:28
Комментарии

Я уже пробовал оба ваших предложения, но они не сработали. Предоставленный код использует WP_Query для запроса записей - я добавил комментарии там, где, КАК МНЕ КАЖЕТСЯ, я использую WP_Query. В цикле из WP_Query я хочу использовать значение метаполя _like_amount.

user51590 user51590
26 мая 2014 г. 22:26:12
0

Оригинальный автор указывает, что это решение:

global $post;

$likes = get_post_meta( $post->ID, "_like_amount", true);

Проблема заключалась в получении ID текущей записи

27 мая 2014 г. 01:56:56