Hoxe en día é bastante habitual en WordPress ter que utilizar Custom Post Types (CPT a partir de agora) e ter que establecer “relacións” entre eles. Un posible exemplo sería o caso de que no noso WordPress teñamos que mostrar información de libros e autores. Neste caso, a relación entre libros e autores é m a n, de tal forma que un autor pode ter varios libros e un libro pode ser de varios autores. Imos, o habitual en calquera sistema de base de datos relacional e un exemplo moi común.

O problema é que WordPress non xestiona estas relacións como un SGBD relacional senón usando a súa propia estrutura de datos e que non segue este modelo. As táboas que WordPress usa para gardar o noso contido son wp_posts e wp_posts_meta, establecéndose unha relación 1 a n entre ambas as táboas. Nestas dúas táboas almacénase a información dos posts, paxinas, etc. A estrutura de campos é a seguinte:

Modelo de datos de wordpress

Isto quere dicir que, aínda que cremos varios CPT non se crean táboas adicionais como fariamos nun modelo relacional, senón que toda esta información almacénase nestas 2 táboas (con algunhas excepcións que non entrarei a comentar).

Estes CPT pódense crear usando un plugin ou directamente en WordPress. No meu caso particular uso usar Toolset, é un plugin moi completo e que uso habitualmente na parte de backend para crear os CPT e establecer as relacións entre eles. Ten unha parte para frontend que coñezo e que usei nalgunha ocasión pero que non serve para o que queremos neste caso. Máis adiante explicar porque non serve.

Neste exemplo creei tres CPT: autores, libros e autores-libros con Toolset . Se queres mais información de como crear estes CPT remítoche á documentación de Toolset que é moi completa, aquí tes unha ligazón que explica como facelo.

Como decía non vou a entrar no detalle de como se crean con Toolset, simplemente indicar que os slug dos meus CPT son “autor”, “libro” e “autor-libro”.

Imos co problema en cuestión. Me facía falta montar unha páxina que mostrará a portada dos libros coa posibilidade de filtrar pola procedencia do autor e o sexo. Estes dous campos son Custom Fields (CF a partir de aquí) do CPT ·”autor“. Como se pode ver, os filtros aplícanse sobre un CPT e a información que se mostra é doutro CPT, a relación “virtual” entre ambos os CPT establécese a través do CPT “autor-libro“, xerado tamén con Toolset.

Inicialmente pensei que usando WP_Query podería realizar unha consulta na que puidese dicirlle “selecciona todos os libros de autores da procedencia=X e de sexo=E“. Polo que puiden comprobar e probar isto non é posible e tampouco é posible facelo usando a parte de Frontend de Toolset. Toolset dispón dunha seria de plugins para xerar vistas e persoais a partir dos CPT creados co propio Toolset pero só serven para filtros e listaxes que usen campos dun CPT, non me permitia filtrar por campos de diferentes CPT como necesitaba neste caso.

Lémbrovos que neste caso quería mostrar información do CPT libros (portada, titulo do libro e ligazón ao detalle do libro) pero filtrando os datos por campos doutro CPT como é “autor“. Neste caso quería filtrar por “sexo” e “procedencia” do autor.

Como comentei anteriormente, usando WP_Query e ata onde sei, non era posible realizar unha consulta que uniese os tres CPT e me permitiese filtrar por procedencia e sexo. E decir, facer algo similar ao seguinte:

Como podemos intuir estou realizando unha consulta filtrando polo CF “sexo” (ao crearlo con Toolset o slug é wpcf-sexo) e procedencia (ao crear este CF o slug é wpcf-procedencia).

Isto non funciona porque WordPress non coñece e non pode xestionar esta relación virtual que establecín con Toolset entre estos CPT e por tanto non pode darme o resultado esperado.

Como isto nin nada semellante funcionaba tiña 2 alternativas ou quizá máis, por unha banda executar directamente unha consulta SQL sobre WordPress, usando a clase wpdb ou ben usar WP_Query pero en lugar de facer unha soa consulta realizar varias para obter o resultado esperado.

A primeira opción ténteina, pero non fun capaz de crear unha consulta SQL que me devolvese os resultados que me facían falta. Tratarei de explicar no seguinte apartado porque non puiden facelo

Almacenamento dos datos en WordPress

Para entender porque non puiden facelo cunha consulta é necesario facer un inciso para explicar como almacena esta información wordpress. Toda a información dos autores e libros almacénase nas táboas wp_posts e wp_postmeta. Neste punto, vou explicar tamén como almacena Toolset o CF e os CPF para poder establecer a relación “virtual” entre estas táboas.

Cando se crea un novo autor insérese un rexistro na táboa wp_posts similar ao seguinte(*)

IDpost_titlepost_excerptpost_contentpost_datepost_typepost_name
135Nombre autorresumenBla bla blaautornombre_autor

Isto seria un rexistro xerado ao inserir un autor. Asociado a este rexistro xéranse na táboa wp_postmeta unha serie de rexistros asociados ao CF do autor, por exemplo para os campos polos que queremos facer consúltaa procedencia e sexo. Como diciamos anteriormente Toolset almacena internamente estes campos co slug wpcf-procedencia e wpcf-sexo. Esta información aparece na táboa wp_postmeta para un autor determinado co ide 135.

meta_idpost_idmeta_keymeta_value
1346135wpcf-procedenciaGalicia
1926135wpcf-sexo1

Neste caso vemos que se vinculan co autor polo post_id = 135, que é o mesmo ID da táboa wp_posts.

Ademais de todo isto, necesitamos saber como establecer a relación cos libros que sexan dese autor. Tamén fai falta xerar na táboa wp_posts un rexistro por cada libro e x rexistros na táboa wp_postsmeta co CF dos libros. Vémolo nas seguintes táboas para un libro determinado:

IDpost_titlepost_excerptpost_contentpost_datepost_typepost_name
511Nombre libroResumneBla bla blalibronombre libro

E no caso dos campos adicionais (CF de libros) en wp_postmeta, por exemplo os campos edición e tipo de obra

meta_idpost_idmeta_keymeta_value
2316511wpcf-edicion4
2317511wpcf-tipo-obra1

En todo este proceso queda un último punto para unir todo, que é como se vinculan os libros aos autores. Isto faise a través do CPT “autor-libro“. Este CPT defínese como fillo de libro e de autores cando se definen en Toolset. Mais información disto na seguinte ligazón .

Neste caso, Toolset para xestionar estas relacións, xera un slug da forma “_wpcf_belongs_xxxx_id“, onde xxxx é o nome do CPT relacionado, nos nosos casos van ser “autor” e “libro“. Por tanto, terá a forma “_wpcf_belongs_autor_id” e “_wpcf_belongs_libro_ide

E teremos unha entrada na táboa wp_posts similar á seguinte:

IDpost_titlepost_excerptpost_contentpost_datepost_typepost_name
512autor-libro512resumenautor-libroautor-libro512

E na táboa wp_postmeta dúas entradas que relacionan este rexistro co libro e autor correspondente e que se obteñen a partir do slug anteriores (“_wpcf_belongs_autor_id” e “_wpcf_belongs_libro_id” ) e dos ids de autor (135), libro (511) e autor-libro (512)

meta_idpost_idmeta_keymeta_value
2320512_wpcf_belongs_libro_id511
2321512_wpcf_belongs_autor_id135

Con isto péchase o circulo e establécese a relación entre autores e libros. Como se pode comprobar toda a información xérase en 2 táboas entre as que non existen relacións mais alá das creadas de forma virtual a través dos slugs dos campos e do Cf. A idea de facer unha consulta SQL que me permitise obter todos os murais para os autores que sexan dun sexo determinado víaa sumamente complicada, así que opte pola segunda opción.

Realizar o filtro

O proceso que ía implementar resumíase en facer unha primeira consulta na que seleccionasen os libros e outra consulta posterior onde obtivese os autores dese libro e comprobase se son do sexo e procedencia que se selecciona no filtro. Este achegamento é pouco eficiente comparado cunha consulta SQL pero non atopei outra alternativa

Toolset acaba de sacar un API que esta en Beta para Toolset Type 3.0 que parece que soporta este tipo de consultas a través de WP_Query . Non o probei así que tampouco podo dar máis información.

O primeiro que necesitaba era obter todos os libros usando WP_Query. A consulta pintaba similar á seguinte:

Unha vez feita esta consulta tenia que obter os autores deses libros para ver se cumprían as condicións do filtro que se estaba aplicando. Neste caso, se eran do sexo e procedencia seleccionada. Isto o facía dentro do bucle pero primeiro tiña que consultar a información en “autor-libro” para saber con que autores estaban vinculados os libros obtidos na primeira consulta.

Imos a explicar este código con máis detalle. Inicialmente obteño todos os libros coa consulta inicial. No bucle proceso cada un destes libros e para cada un deles obteño os ids da relación “autor-libro” para ese libro, que evidentemente poden ser varios. É importante indicar que o que obteño aquí é o ide da relación “autor-libro“, aínda non cheguei a obter os datos do autor.

Como se pode ver na creación da consulta indico que só me devolva os ids coa instrucción ‘fields’ => ‘ids’

Unha vez que teño estes ids fago a seguinte chamada

que obtén os ids na táboa wp_posts que establecen a relación entre autores e libros do CPT “autor-libro

Despois disto entro nun bucle no que proceso cada un dos rexistros devoltos nesa consulta para saber os ids dos autores e poder ver se cumpren os filtros. Isto fágoo na seguinte instrución

Isto vaime a devolver un array que contén todos os rexistros que existan para ese ide na táboa wp_postmeta, que poden ser varios, e no caso que nos ocupa existirán polo menos estes 2

meta_idpost_idmeta_keymeta_value
2320512_wpcf_belongs_libro_id511
2321512_wpcf_belongs_autor_id135

Fixarvos que na consulta anterior eu vou estar recuperando estes 2 rexistros porque realmente estou a consultar polo post_ide = 512, que é o ide autor-libro. Unha vez obtidos estes resultados no array $datos_autor_libro, o que necesito saber é o ide do autor e isto obtéñoo da seguinte forma

Que me vai a devolver o valor 135. Este é o ide do autor. Con leste ide podo obter todos os datos dese autor con

A partir de aquí o que teño que facer, e que non puxen no código é comprobar se cumpre os filtros que se estean aplicando de sexo e procedencia. Esta comprobación sería algo así

Ata aquí esta longa explicación. O proceso é un pouco confuso pero non atopei outra forma de facelo máis sinxela. A miña conclusión é que WordPress cando se queren ter relacións 1 a N ou M a N entre CPT e mostrar resultados que impliquen filtros entre diferentes ?táboas? e diferentes CF faino un pouco complicado. Non é moi recomendable facer este tipo de filtros e consultas, aínda que moitas veces son necesarios. Unha opción sería utilizar categorías e etiquetas pero tampouco me parece unha boa solución. Outra cuestión sería poder facelo a través dalgún plugin que facilitase esta tarefa, como parece que o fai a nova versión de Toolset pero que aínda está en beta.

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información.plugin cookies

ACEPTAR
Aviso de cookies