La siguiente es una publicación invitada de cristian nolen. Christian detalla una situación en la que los datos se organizan de manera inteligente y razonable, pero es un poco complicado consultarlos correctamente. Él detalla una solución que no va demasiado lejos en las malas hierbas para hacerlo bien.
Si alguna vez ha realizado algún desarrollo de WordPress, es probable que haya necesitado crear tipos de publicaciones personalizadas y registrar taxonomías. Trabajar con taxonomías es sencillo cuando la relación es uno a uno, es decir, “Obtén todos los términos de la taxonomía, usa get_terms()
, u obtenga todos los términos asociados con la publicación actual, use get_the_terms()
.”
Pero, ¿qué hace cuando necesita que los resultados devueltos sean relativos a otra taxonomía? Ninguna de las funciones típicas ayuda. Antes de profundizar en la solución, echemos un vistazo más de cerca al problema. El caso de uso es un sitio web de cartera que ofrece una variedad de servicios en múltiples mercados. Nuestra configuración es la siguiente:
- Tipo de publicación personalizada: Portafolio
- Taxonomía: Servicios
- Condiciones: Desarrollo, Ilustración, Fotografía, Diseño de Impresión, Diseño Web
- Taxonomía: Mercados
- Condiciones: Cívico, Corporativo, Educación, Salud, Sin Fines de Lucro
Este sitio requiere el uso de una plantilla de taxonomía para ambos Servicios y Mercados. Cuando un visitante llega a una de estas páginas de taxonomía, se muestra un diseño de pestaña que muestra elementos de cartera para mercados asociados (si está viendo un servicio) o servicios asociados (si está viendo un mercado).
En la captura de pantalla anterior, estoy mostrando una página de Servicio de fotografía. he usadoget_terms('market')
para recuperar los mercados válidos (asignados a un $markets
variable). Recorro cada mercado para crear mi pestaña y luego uso WP_Query
para recuperar todos los elementos de parque correspondientes. El tax_query
El parámetro se usa para restringir los resultados al mercado y servicio actual (definido usando get_query_var('term')
en este caso).
Lo primero que notamos es una vergonzosa pestaña vacía de “Civic” que resalta el hecho de que los servicios no se han proporcionado en este mercado. Para empezar, es la primera pestaña que ve un visitante cuando aterriza en esta página.
La solución
Pasé una cantidad significativa de tiempo investigando una resolución. La única solución que encontré involucró consultar la base de datos usando wpdb. Sí, esta era una solución, pero no se sentía bien. Sabía que debe haber una forma integrada de manejar este caso de uso.
Después de profundizar en el Codex de WordPress, descubrí wp_get_object_terms()
. La descripción de la función es la siguiente:
Recupera los términos asociados con los objetos dados en las taxonomías proporcionadas.
El ejemplo proporcionado es muy similar a uno que encontraría para get_the_terms()
. La clave es que el parámetro del objeto puede ser una matriz.
El objeto al que queremos pasar wp_get_object_terms()
es una matriz de ID de publicación. La forma más eficiente que se me ocurrió de construir esta matriz fue usando get_posts()
con el parámetro de campos establecido en “ids”. podrías usar WP_Query
, pero opté por get_posts() porque:
get_posts()
devuelve una matriz frente a un objeto- Nunca confundiré mi inicial
get_posts()
Llamada deWP_Query
utilizado dentro del contenido tabulado.
$service_slug = get_query_var('term');
$service_post_IDs = get_posts(array(
'post_type' => 'portfolio',
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'service',
'field' => 'slug',
'terms' => $service_slug
)
),
'fields' => 'ids'
));
Lo anterior es cómo obtenemos el subconjunto correcto de ID de publicación. Como se mencionó anteriormente, recupero el slug de servicio actual usando get_query_var('term')
y asignarlo a la $service_slug
variable. Esto se usa en tax_query
para asegurarnos de que solo obtengamos ID de publicación que estén asignados al término de taxonomía actual. Al establecer el fields
parámetro a ids
el resultado es una matriz indexada de ID de publicaciones.
Ahora que tengo la matriz de ID de publicación, puedo reemplazar get_terms()
con lo siguiente:
$markets = wp_get_object_terms($service_post_IDs, 'market');
Cuando actualizo la página, la pestaña “Civic” desaparece y tenemos una pestaña con el contenido correcto.
Podría parar aquí. Pero ahora los argumentos usados dentro WP_Query
me estan molestando
$args = array(
'post_type' => 'portfolio',
'posts_per_page' => -1,
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'market',
'field' => 'slug',
'terms' => $m->slug,
),
array(
'taxonomy' => 'service',
'field' => 'slug',
'terms' => $service_slug,
),
)
);
Sí, lo anterior funciona bien. Pero siento que estoy duplicando mis esfuerzos con respecto a mi tax_query
. Lo que podemos hacer es refactorizar tax_query para incluir solo el mercado actual y aprovechar el post__in
parámetro con la matriz de ID de puestos de servicio.
$args = array(
'post_type' => 'portfolio',
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'market',
'field' => 'slug',
'terms' => $m->slug,
)
),
'post__in' => $service_post_IDs
);
El resultado inicial es el mismo, pero ahora los argumentos de consulta son más delgados y fáciles de leer. Lo más importante es que ahora tiene una plantilla que muestra información válida a sus visitantes.