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

44

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

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

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

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

Пример:

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

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

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

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

  • Функция WP, чтобы получить это. или
  • пользовательский запрос, чтобы получить это максимально эффективно.
mikkelbreum
источник
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.
*/

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

t31os
источник
3
Также забавный факт для будущих зрителей, если вы хотите использовать только уникальные мета-значения - вы вводите DISTINCTсразу после SELECTфункции, указанной выше. Может быть полезно
Howdy_McGee
Я думаю, что это чрезвычайно полезно
Пабло С.Г. Пачеко
Как это сделать, и вернуть отсортированные значения ?, Я думаю, что с помощью ORDER, но я не могу понять, как его использовать
efirvida
14

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

Lehooo
источник
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
");

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

Bainternet
источник
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'" );
Wiki
источник
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)
benz001
источник
0

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

 $key = get_post_custom_values( 'key' );

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

Dev
источник
Обратите внимание, что по умолчанию используется текущее сообщение, когда post_id не указан.
birgire