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 book
tiene 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 book
tiene 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.
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.
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