How do I create a many-to-many relationship between two custom post types?
Given type A and given type B, I’d like to be able to show all Bs that relate to a given A, and all As that relate to a given B.
How do I create a many-to-many relationship between two custom post types?
Given type A and given type B, I’d like to be able to show all Bs that relate to a given A, and all As that relate to a given B.
You must be logged in to post a comment.
As Milo noted, there is no built in way to do a many to many relationship between two custom post types.
That being said, these days it isn’t too hard to do it yourself without a plugin if wanted.
I do many to many relationships between custom post types by using non-singular post meta.
e.g. Books and Authors
Stick an author_id post meta (non-singular) on a book and you can now have:
Adding the relationships into the post editors
The below class takes care of creating this kind of relationship and adding it to post editors. For this example, it is assumed that one post type is called ‘book’ and the other is called ‘author’. Yes, terrible naming … but it helps illustrate how it works.
One might need to change ‘author’ to ‘writer’ or some such as I can’t remember off the top of my head if author is an actual post type or not.
Setting up 2 author meta boxes
We set up one author meta box to show the book relationships and another to hold some extra data about the author.
We do not put this all in one meta field because we want to be able to easily query book author relationships.
If we stuck the book_ids into the serialized array used for the author extra data, we could not easily query it.
By using non-singular post meta named ‘_author_id’ on each book we gain the ability to:
If we wanted to be able to easily query other things about an author, we could either break them out of the serialized array or use SQL like clauses to seek them out even if they are in an array, but breaking them out is much cleaner.
We use a calling function since we need the details meta in multiple functions.
We also use a get_defaults call so we can keep the defaults noted in once place in case we need to change them.
The Author Details Box
We just grab their meta and display it in text boxes for this example.
The Related Books Box
We build a list of check boxes for this example so the user can set them all if wanted.
We could add a check_all type box with some javascript, break them out by category, etc.
And yes, if we had thousands of books in the system this would probably not be the best plan, but it works great if we only have a few hundred books.
Grabbing all posts of a type
We use a generic function for this as we need it for both post types.
Getting books for an author
Books have an _author_id set on them which is a multi-value post meta so we can have one book related to many authors.
This function grabs the book ids as an array.
Setting up book related authors
We will just have a related authors box for now.
We draw it out just like the author related books box.
Getting a books related authors
This is just a matter of grabbing the post meta and noting that it is not singular.
Saving our meta box data
We do a bunch of sanity checking and then, if needed, hand off actual processing to helper functions.
Saving Author Data
We have two meta boxes to process, our details box and our related books box.
For the details box, processing is simple. I only update if absolutely needed.
For the related books box, we compare our currently related books to those checked by the user and add or remove relationships as needed, talking care to make sure we don’t quash the many to many relationship we set up.
Note: We are working on book meta data in the related books section, not our own.
Saving Related Authors for Books
Pretty much the same as saving related books for authors, except we are working on our own post meta.
Getting the class to work
So long as you load the class before things are set up ( include it or inline it in a plugin, locate_template the class function in your theme functions.php, etc ), you can use it easily as follows:
It will take care of setting everything up
Some example front end uses
Now that we have set up meta boxes in the admin panels that let us easily mark all books for an author and vice versa, let’s put things to work.
First, a couple of starting helper functions:
Getting all books for a given author
Given an author id, returns an array of book post objects.
Grab an authors extra data
We could shape this up by setting defaults and/or mapping keys to nicer names.
For now, we just want the data or an empty array.
Getting Book and Extra Data in the Main Loop
This example assumes you are in the main loop (e.g. one of the following is true)
That being said, anywhere we have a known author id we can use the above helper functions to pull their books and extra information.
Getting Book Authors
Below is a helper function to pull all authors given a book id.
To use get_authors_for_book_id, you might use it on a single book template or book archive template as follows:
End Results
You now have two post types with a many to many relationship and some helper functions to pull data where needed.
There is a lot of room for improvement in this code, but it should do the trick.
WordPress doesn’t have a way to natively do many-to-many relationships, have a look at the Posts 2 Posts plugin to enable this.
Nowadays, you should use add_meta_box_{posttype} instead of add_meta_box_for{posttype} :