Obtenga publicaciones de WP basadas en múltiples pares meta clave/valor usando IN

5 minutos de lectura

Tengo algunos problemas para formatear mi consulta para obtener una lista de publicaciones de la base de datos según el valor de dos valores meta. Estoy usando WordPress 4.9.4 y necesito usar $wpdb->get_results() y no un normal get_posts() llamada de función con argumentos.

Esto es lo que tengo hasta ahora, pero si trato de incluir el IN parte de la consulta de MySQL, no devuelve nada, pero debería devolver al menos una publicación.

global $wpdb;

$posts = $wpdb->get_results(
    $wpdb->prepare(
        'SELECT ' . $wpdb->prefix . 'posts.*, ' . $wpdb->prefix . 'postmeta.* FROM ' . $wpdb->prefix . 'posts, ' . $wpdb->prefix . 'postmeta WHERE ' . $wpdb->prefix . 'posts.post_type = %s AND ' . $wpdb->prefix . 'postmeta.post_id = ' . $wpdb->prefix . 'posts.ID AND (' . $wpdb->prefix . 'postmeta.meta_key = %s AND ' . $wpdb->prefix . 'postmeta.meta_value = %s) AND (' . $wpdb->prefix . 'postmeta.meta_key = %s AND ' . $wpdb->prefix . 'postmeta.meta_value IN (%s)) ORDER BY ' . $wpdb->prefix . 'posts.post_title ASC LIMIT %d OFFSET %d',
        'book',
        'book_genre',
        $genre,
        'category',
        '239, 440',
        $limit,
        $offset
    )
);

La consulta anterior debería obtener todas las publicaciones donde:

  • la publicación tiene un post_type de book en wp_posts
  • tiene una meta_clave de book_genre y meta_valor de fiction en wp_postmeta
  • tiene una meta_clave de category y meta_valor de 239, 440 en wp_postmeta
  • limitar los resultados a xyz
  • compensar los resultados de xyz

Sin embargo, la consulta anterior devuelve un valor de null si yo var_dump( $posts ); en la página, así que me imagino que en parte está causando algún tipo de conflicto con la primera regla meta clave/valor, ¿quizás?

Si elimino el IN parte de la consulta obtiene todo como se esperaba menos el filtrado de las categorías, por supuesto, que me gustaría. Los identificadores de categoría son una matriz de identificadores que se convierten en una cadena separada por comas usando PHP implode().

Por ejemplo:

  • Correo 1 tiene un post_type de booktiene un par meta clave/valor de book_genre y fiction y tiene un par clave/valor meta de ‘categoría’ y 440 entonces deberían incluirse utilizando la consulta anterior.

  • Correo 2 tiene un post_type de booktiene un par meta clave/valor de book_genre y fiction y tiene un par clave/valor meta de ‘categoría’ y 323 entonces no debe incluirse utilizando la consulta anterior.

  • No está más claro y nadie debería tener que descifrar esto. Si necesita ayuda con su consulta, luego solo bríndenos una consulta MySQL sin procesar y una muestra de datos de entrada/salida. Si su consulta ya funciona y necesita ayuda de PHP, díganos esto.

    – Tim Biegeleisen

    27/03/2018 a las 10:00

  • Cuando digo consulta, quiero decir $wpdb consulta que se convierte en una consulta MySQL a través del método de consulta de WordPress. Entiendo que es una pregunta difícil de hacer y responder, pero es una que no he encontrado antes, o es única o podría haberla expresado de manera diferente. La esencia es cómo lo escribo de una manera que seleccione publicaciones basadas en dos pares clave/valor meta. Parece que está escrito incorrectamente para admitir dos.

    usuario7236046

    27 de marzo de 2018 a las 10:06

Obtenga publicaciones de WP basadas en multiples pares meta clavevalor
rotonda magica

Tienes que unirte a la post_meta mesa dos veces. Aquí hay algo de teoría de la base de datos.

Cuando une tablas, en teoría se crea y filtra una tabla temporal que contiene todos los elementos de la primera tabla combinados con todos los elementos de la segunda tabla. Entonces, si, por ejemplo, solo tiene 1 metaelemento por publicación y tiene 3 publicaciones, entonces tiene

+-------+----------+
|post_id|post_title|
+-------+----------+
|   1   | 'Post 1' |
|   2   | 'Post 2' |
|   3   | 'Post 3' |
+-------+----------+

y

+-------+----------+----------+------------+
|meta_id| post_id  | meta_key | meta_value |
+-------+----------+----------+------------+
|   10  | 1        |  k1      | v1         |
|   11  | 2        |  k1      | v2         |
|   12  | 3        |  k1      | v3         |
+-------+----------+----------+------------+

Y la tabla unida temporal “teórica” ​​es:

+---------+------------+----------+----------+-----------+-------------+
|p.post_id|p.post_title|pm.meta_id|pm.post_id|pm.meta_key|pm.meta_value|
+---------+------------+----------+----------+-----------+-------------+
|   1     | 'Post 1'   |   10     | 1        |  k1       | v1          |
|   1     | 'Post 1'   |   11     | 2        |  k1       | v2          |
|   1     | 'Post 1'   |   12     | 3        |  k1       | v3          |
|   2     | 'Post 2'   |   10     | 1        |  k1       | v1          |
|   2     | 'Post 2'   |   11     | 2        |  k1       | v2          |
|   2     | 'Post 2'   |   12     | 3        |  k1       | v3          |
|   3     | 'Post 3'   |   10     | 1        |  k1       | v1          |
|   3     | 'Post 3'   |   11     | 2        |  k1       | v2          |
|   3     | 'Post 3'   |   12     | 3        |  k1       | v3          |
+---------+------------+----------+----------+-----------+-------------+

Luego dices: WHERE p.id = pm.post_id

y esto filtra la tabla temporal para que sea:

+---------+------------+----------+----------+-----------+-------------+
|p.post_id|p.post_title|pm.meta_id|pm.post_id|pm.meta_key|pm.meta_value|
+---------+------------+----------+----------+-----------+-------------+
|   1     | 'Post 1'   |   10     | 1        |  k1       | v1          |
|   2     | 'Post 2'   |   11     | 2        |  k1       | v2          |
|   3     | 'Post 3'   |   12     | 3        |  k1       | v3          |
+---------+------------+----------+----------+-----------+-------------+

Por lo tanto, solo tiene una fila para cada publicación + valor meta. Su consulta solicita filas que tengan ambos meta_key = category y meta_key = book_genre` que no existen.

Así que necesitas una mesa que se una a la postmeta mesa en TWICE.

Puede hacer esto creando un alias en la tabla a medida que se une a ellos. Perdóname por simplificar:

SELECT wp_posts.*, pm1.*, pm2.*
FROM
  wp_posts
  wp_postmeta as pm1
  wp_postmeta as pm2
WHERE pm1.post_id = wp_posts.ID
  AND pm2.post_id = wp_posts.ID
  AND ...etc

Aquí tiene dos copias unidas de la tabla postmeta con alias para pm1 y pm2 (ya que AMBOS no pueden ser llamados wp_postmeta en la consulta

A continuación, puede solicitar:

AND pm1.meta_key = 'category'
AND pm1.meta_value = X
AND pm2.meta_key = 'book_genre'
AND pm2.meta_key IN (123,456)

Con suerte, puedes unir el resto de eso.

También creo que puedes hacer esto con WP_Query si quieres ir por ese camino.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad