получение всех значений для ключа настраиваемого поля (кросс-пост)


44

Я знаю, как получить значение настраиваемого поля для конкретного поста.

get_post_meta($post_id, $key, $single);

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

Кто-нибудь знает эффективный способ сделать это? Я не хотел бы перебирать все идентификаторы постов в БД.

Пример:

4 сообщения с разными значениями для настраиваемого поля «Настроение». 2 сообщения имеют значение «счастливый», 1 сообщение имеет «гнев» и 1 сообщение имеет «грустный»

Я хочу выводить: по всем имеющимся у нас сообщениям: два счастливых, один злой и один печальный автор (ы).

Но для МНОГО постов.

То, что я ищу, это либо:

  • Функция WP, чтобы получить это. или
  • пользовательский запрос, чтобы получить это максимально эффективно.

5
Похоже, вы используете это в качестве таксономии. Почему бы просто (автоматически) не добавить термин в эти сообщения при сохранении? Сделал бы запрос намного проще.
— Кайзер

@ Кайзер Я не могу отблагодарить тебя за то, что ты гений!
— user2128576

Ответы:


58

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

Конечно, не все функции одинаковы, и целенаправленное упоминание относится к методу WPDB , get_colкоторый возвращает простой плоский массив запрашиваемых данных, я специально упомяну это, потому что следующий пример вызовет этот метод ,

WordPress - WPDB Выбор столбца данных
$ wpdb-> get_col ()

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

function get_meta_values( $key = '', $type = 'post', $status = 'publish' ) {

    global $wpdb;

    if( empty( $key ) )
        return;

    $r = $wpdb->get_col( $wpdb->prepare( "
        SELECT pm.meta_value FROM {$wpdb->postmeta} pm
        LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
        WHERE pm.meta_key = %s 
        AND p.post_status = %s 
        AND p.post_type = %s
    ", $key, $status, $type ) );

    return $r;
}

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

$movie_ratings = get_meta_values( 'rating', 'movies' );

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

// Print the meta values seperate by a line break
echo implode( '<br />', get_meta_values( 'YOURKEY' ));

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

$movie_ratings = get_meta_values( 'rating', 'movies' );
if( !empty( $movie_ratings ) ) {
    $num_of_ratings = array();
    foreach( $movie_ratings as $meta_value )
        $num_of_ratings[$meta_value] = ( isset( $num_of_ratings[$meta_value] ) ) ? $num_of_ratings[$meta_value] + 1 : 1;
}

/*
Result:
Array(
    [5] => 10
    [9] => 2
)
// ie. there are 10 movie posts with a rating of 5 and 2 movie posts with a rating of 9.
*/

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


3
Также забавный факт для будущих зрителей, если вы хотите использовать только уникальные мета-значения - вы вводите DISTINCTсразу после SELECTфункции, указанной выше. Может быть полезно
— Howdy_McGee

Я думаю, что это чрезвычайно полезно
— Пабло С.Г. Пачеко

Как это сделать, и вернуть отсортированные значения ?, Я думаю, что с помощью ORDER, но я не могу понять, как его использовать
— efirvida

14

Я просто хотел бы добавить одну маленькую вещь в код t31os выше. Я изменил «SELECT» на «SELECT DISTINCT», чтобы исключить повторяющиеся записи, когда сам использовал этот код.


1
Я могу представить себе случаи, когда было бы правильно иметь несколько мета-значений одного и того же значения, и, таким образом, я не добавлял это в мой код. Если вы хотите разные значения, это будет путь. Кроме того, вы также можете добавить это в качестве аргумента для функции (чтобы вы могли использовать ее или нет, в зависимости от ситуации).
— t31os

10

Это не хорошо или не нужно использовать глобальный $ wpdb:

// function to grab all possible meta values of the chosen meta key.
function get_meta_values( $meta_key,  $post_type = 'post' ) {

    $posts = get_posts(
        array(
            'post_type' => $post_type,
            'meta_key' => $meta_key,
            'posts_per_page' => -1,
        )
    );

    $meta_values = array();
    foreach( $posts as $post ) {
        $meta_values[] = get_post_meta( $post->ID, $meta_key, true );
    }

    return $meta_values;

}

$meta_values = get_meta_values( $meta_key, $post_type );

В большинстве случаев это будет мой предпочтительный метод. Он делает пять запросов, а не один, но, поскольку он использует стандартные процедуры WordPress для их генерации и отправки, будет задействовано любое специфичное для платформы кэширование (такое как объектное кэширование в WP Engine или некоторый случайный плагин). Данные также будут хранится во внутреннем кеше WordPress на время запроса, поэтому при необходимости его не нужно будет снова извлекать из базы данных.
— Эндрю Динмор

Любые фильтры также будут применяться к данным, что может быть чрезвычайно важно, например, на многоязычном сайте. И наконец, поскольку он использует только стандартные функции ядра WordPress, вероятность его появления в будущем обновлении значительно ниже.
— Эндрю Динмор

4

самый быстрый способ был бы пользовательский запрос SQL, и я не уверен, но вы можете попробовать

$wpdb->get_results("
  SELECT posts.* , COUNT(*) 'moodcount'
  FROM $wpdb->posts as posts
  JOIN $wpdb->postmeta as postmeta
  ON postmeta.post_id = posts.ID
  AND postmeta.meta_key = 'Mood'
  GROUP BY postmeta.meta_key
");

Если что, то это начало.


1
спасибо, но не следует ли избегать нестандартных вопросов «любой ценой»? Я бы предпочел использовать слой абстракции WP (так он называется?) ... но, конечно, если это невозможно ...
— mikkelbreum

Пользовательские запросы, если они написаны правильно, могут быть лучше, и вам следует избегать их, только если вы не знаете, что делаете.
— Bainternet

1
Я согласен с mwb .custom запросы очень полезны и практичны, но я думаю, что они также намного тяжелее на БД .. особенно с использованием функций SRT ..
— krembo99

3

Для получения всех мета значений мета ключом

Проверьте wp-> db wordpress codex

$values = $wpdb->get_col("SELECT meta_value
    FROM $wpdb->postmeta WHERE meta_key = 'yourmetakey'" );

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

Хотя это правда, что вы можете получать значения из других типов и статусов записей, бывают случаи, когда все, что вам нужно, это значения, и вы не использовали этот meta_key нигде, кроме как там, где он вам нужен. Если все / большинство значений уникальны, это может быть лучшим решением.
— Люк Гедеон

2

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

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

В этом случае я больше не проверяю тип сообщения и исключаю пустые строки:

    $r = $wpdb->get_results(  $wpdb->prepare( "
        SELECT pm.meta_value AS name, count(*) AS count  FROM {$wpdb->postmeta} pm
        LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
        WHERE pm.meta_key = '%s'
        AND pm.meta_value != '' 
        AND p.post_type = '%s'
        GROUP BY pm.meta_value
        ORDER BY pm.meta_value          
        ", $key, $type) 
        );
    return $r;

В частности это

Это вернет массив объектов примерно так:

array  
 0 => 
 object(stdClass)[359]
  public 'name' => string 'Hamish' (length=6)
  public 'count' => string '3' (length=1)
 1 => 
 object(stdClass)[360]
  public 'name' => string 'Ida' (length=11)
  public 'count' => string '1' (length=1)
 2 => 
 object(stdClass)[361]
  public 'name' => string 'John' (length=12)
  public 'count' => string '1' (length=1)

0

Используйте следующее с foreach

 $key = get_post_custom_values( 'key' );

Предполагается, что имя вашего настраиваемого ключа поля


Обратите внимание, что по умолчанию используется текущее сообщение, когда post_id не указан.
— birgire
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.