obtener todos los valores para una clave de campo personalizada (cross-post)

44

Sé cómo obtener un valor de campo personalizado para una publicación específica.

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

Lo que necesito es obtener todos los valores asociados con una clave de publicación personalizada específica, en todas las publicaciones .

Alguien sabe de una manera eficiente de hacer esto? No me gustaría recorrer todas las ID de publicación en la base de datos.

Ejemplo:

4 publicaciones, todas con diferentes valores para un campo personalizado llamado 'Mood'. 2 publicaciones tienen el valor 'feliz', 1 publicación tiene 'enojado' y 1 publicación tiene 'triste'

Quiero publicar: en todas las publicaciones que tenemos: dos autores felices, uno enojado y uno triste.

Pero por MUCHAS publicaciones.

Lo que estoy buscando es:

  • una función WP para obtener esto. o
  • una consulta personalizada para obtener esto de la manera más eficiente posible.
Mikkelbreum
fuente
55
Parece que estás usando esto como una taxonomía. ¿Por qué no simplemente (automáticamente) agregar un término a estas publicaciones al guardar? Haría las consultas mucho más fáciles.
kaiser
@kaiser ¡No puedo agradecerte lo suficiente por ser un genio!
user2128576

Respuestas:

58

Un enfoque posible sería utilizar uno de los métodos auxiliares en la clase WPDB para hacer una consulta meta basada más refinada. Sin embargo, la advertencia del uso de algunas de estas funciones es que, por lo general, no se obtiene una matriz simple de datos y, por lo general, se deben hacer referencias innecesarias a las propiedades de los objetos, incluso si solo se solicita una columna o fila.

Por supuesto, no todas las funciones son iguales, y se hace una mención intencional al método WPDB , get_colque devuelve una simple matriz plana de los datos consultados, hago esta mención específicamente porque el siguiente ejemplo recurrirá a este método .

WordPress - WPDB Seleccionando una columna de datos
$ wpdb-> get_col ()

Aquí hay una función de ejemplo que consulta la base de datos para todas las publicaciones de un tipo de publicación elegido, estado de publicación y con una metaclave específica (o campo personalizado para los menos técnicos).

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;
}

Entonces, por ejemplo, si desea averiguar qué publicaciones tienen una metaclave de calificación , para las películas de tipo de publicación y desea almacenar esa información dentro de una variable, un ejemplo de dicha llamada sería ...

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

Si no desea hacer nada más que imprimir esos datos en la pantalla, la función de implosión de PHP puede empalmar rápidamente esa simple matriz en líneas de datos.

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

También puede usar los datos devueltos para calcular cuántas publicaciones tienen estos meta valores haciendo un bucle simple sobre los datos devueltos y creando una matriz de los recuentos, por ejemplo.

$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.
*/

Esta lógica podría aplicarse a varios tipos de datos y extenderse para funcionar de muchas maneras diferentes. Así que espero que mis ejemplos hayan sido útiles y lo suficientemente simples como para seguirlos.

t31os
fuente
3
También es un hecho divertido para los futuros espectadores, si desea extraer solo metavalores únicos: escriba DISTINCTjusto después de SELECTen la función anterior. Podría ser útil.
Howdy_McGee
Creo que esto es extremadamente útil
Pablo Pacheco SG
¿Cómo hacer esto y devolver los valores ordenados ?, creo que usando ORDER por pero no puedo entender cómo usarlo
efirvida
14

Solo me gustaría agregar una pequeña cosa al código de t31os anterior. Cambié "SELECT" en "SELECT DISTINCT" para eliminar entradas duplicadas cuando usé este código yo mismo.

Lehooo
fuente
1
Puedo imaginar casos en los que sería válido tener múltiples metavalores del mismo valor, y por lo tanto, no hice esa adición a mi código. Sin embargo, si desea valores distintos, este sería el camino a seguir. Además, también podría agregarlo como argumento para la función (para que pueda usarla o no, según corresponda).
t31os
10

No es bueno o necesario usar el $ wpdb global:

// 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 );
Leon Francis Shelhamer
fuente
Este sería mi método preferido para hacerlo, en la mayoría de los casos. Realiza cinco consultas, en lugar de solo una, pero, dado que utiliza los procedimientos estándar de WordPress para generarlos y enviarlos, cualquier almacenamiento en caché específico de la plataforma (como el almacenamiento en caché de objetos de WP Engine o algún complemento aleatorio) se activará. Los datos también se almacenará en la memoria caché interna de WordPress durante la duración de la solicitud, por lo que no será necesario recuperarlo de la base de datos nuevamente, si es necesario.
Andrew Dinmore
Cualquier filtro también se aplicará a los datos, lo que podría ser extremadamente importante en, por ejemplo, un sitio multilingüe. Por último, dado que usa solo las funciones básicas estándar de WordPress, es mucho menos probable que se rompa con una actualización futura.
Andrew Dinmore
4

la forma más rápida sería una consulta SQL personalizada y no estoy seguro, pero puedes intentar

$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
");

En todo caso, es un comienzo.

Bainternet
fuente
1
gracias, pero ¿no deberían evitarse las preguntas personalizadas "a toda costa"? Yo prefiero usar la capa de abstracción WP (es que cómo se llama?) ... pero por supuesto, si esto no es posible ..
mikkelbreum
Las consultas personalizadas, si se escriben de la manera correcta, pueden ser mejores y solo debe evitarlas si no sabe lo que está haciendo.
Bainternet
1
Estoy de acuerdo con mwb. Las consultas personalizadas son muy útiles y prácticas, pero creo que también son mucho más pesadas en la base de datos ... especialmente con las funciones SRT ...
krembo99
3

Para obtener todos los meta valores por una meta clave

Compruebe wp-> db wordpress codex

$values = $wpdb->get_col("SELECT meta_value
    FROM $wpdb->postmeta WHERE meta_key = 'yourmetakey'" );
Wiki
fuente
3
El problema con este enfoque es la falta de especificidad, obtendrá numerosos resultados de dicha consulta, que podría incluir borradores, elementos descartados, publicaciones, páginas y cualquier otro tipo de publicación que exista. Nunca debe consultar lo que no necesita, la especificidad ciertamente se requiere aquí.
t31os
Si bien es cierto que podría obtener valores de otros tipos de publicaciones y estados, hay momentos en que todo lo que necesita son los valores y no ha utilizado esa meta_key en ningún otro lugar que no sea el que la necesita. Si todos / la mayoría de los valores son únicos, esta puede ser la mejor solución.
Luke Gedeon el
2

No hay ninguna razón por la que no pueda fusionar t31os y el código de Bainternet para tener una declaración preparada reutilizable (estilo wordpress) que devuelva el recuento y los valores en una operación eficiente.

Es una consulta personalizada, pero todavía usa la capa de abstracción de la base de datos de WordPress, por lo que, por ejemplo, no importa cuáles sean realmente los nombres de las tablas o si cambian, y es una declaración preparada, por lo que estamos mucho más seguros de los ataques SQL, etc. .

En este caso, ya no busco el tipo de publicación y excluyo cadenas vacías:

    $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;

En este particular es

Esto devolverá una matriz de objetos así:

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
fuente
0

Use lo siguiente con foreach

 $key = get_post_custom_values( 'key' );

Asume que el nombre de su clave de campo personalizado es

Dev
fuente
Tenga en cuenta que esto predeterminado es la publicación actual, cuando no se especifica post_id.
birgire