My name is Randy Hoyt, and if you want to learn more about me, you can
visit my website randyhoyt.com, or follow me on twitter. I’ll be posting
the slides and the code from this talk up there. I do work at Tree House,
I’m a PHP teacher there, intreehouse.com it’s an online resource for web
development training, for learning HTML, CSS, PHP, and other languages.
Before that I worked at a creative agency called Imaginuity in Dallas,
Texas. We build web sites for clients there. About half of the work we did
was on WordPress. In the last two years Word Press rolled out with custom
post types, and pretty much every site that we built at Imaginuity, we used
custom post types.
Just as a quick example, this is a website for a party factory supply
store. It’s a franchise. They have a number of locations. We had a
locations post type, so you would add them in, add in the location just
like you ad in a post or a page. Then, on the front end of the page we
could have a zip code search. You could put in your zip code, returned a
Google map with your locations nearest to you.
As I mentioned most every site that we built at Imaginiuty has custom post
types, and most of them have multiple post types. The thing that excites me
the most about custom post types is when you start getting some advanced
use cases, where you want to use them together, and relate them together.
Here’s another example that I built at Imaginuity, this is a shopping
website. They run a multi-site registration with fifty or sixty shopping
centers on it. Each shopping center has a store directory, the list of all
the stores that the shopping center has. We have the store directory page.
Underneath the store directory page, we have a couple of post types for
jobs. If you want to work at one of the stores in the center, you can see a
list of all the job openings that they have.
They have sales. They have promotions, maybe 50 percent off this week, off
hats or something. When you relate them together, when a user visits this
page for a specific store, you can see there over in the side bar how we
have a list of all the related sales, and related offers, and the related
There’s a few different ways in Word Press that you can relate word types
together. I think the one I hear people talk most about are custom fields.
You can store, in the WP post meta table, you can store the relationships.
On one of the posts you can have a meta key. That’s how we did it with the
jobs. On the jobs, we had a custom field for store ID and we stored the
related store ID there in the custom fields, the post meta table.
Another way that people are doing post type relationships is they add a
custom table. Some popular plug-ins that extent content types, Pods does
this, it has a separate table for relationships and a post to post plug-in,
if you use that. They create another table. What’s nice about this, is
that you have a number of fields to track data about the relationship.
If you’re going to store, let’s say, actors and movies, for example, and
you want to relate those together. It’s not a parent-child relationship,
and you might want to have extra information about that actor-to-movie
relationship that you store in that table.
The third way, and this is the one that I’m going to spend the rest of my
talk talking about, is a parent-child relationship. This one would use the
post parent column on the post table, to store that relationship. This
won’t work in every case, like the actors and movies. An actor is not the
child of a particular movie, and the movie is not a child of a particular
Those are many-to-many relationships. If you have a one-to-many
relationship, like I had with stores, every job applies to one and only one
store. With the sales, each sale applies to one and only one store.
Then you can use this approach, I call this a “subordinate post” type
relationship. One of the post types is subordinate to one of the other post
types. When you think of parent-child, you probably think of posts that are
of the same type. In the WordPress core, they use this post parent field
for storing the hierarchical page relationship. So this is a snap shot of
the WP posts table in WordPress.
There’s the about page, which is a top level page on this site, and it has
a post parent relationship of zero. Then there are pages beneath that,
location and content page. That are beneath the about page, they have a
post parent, in this case, of 2, that’s the ID of the “About” page. When
you register your own post types, you can easily set up this type of
hierarchy relationship. So that posts within that type have another post of
the same type as its parent.
There’s no way in WordPress’s core API’s to easily register them to be
related across different kinds of post types. WordPress does use that
subordinate post type relationship in core. One example is the revisions.
When you save a page, WordPress will keep a copy of the revision, keep a
copy of that history, and it adds a post type for revision, and it stores
the parent of that revision as the page that it’s a revision of.
You have one post type revisions, that has another post type page as its
parent. A few plug-ins do this as well. If you saw John’s talk on BB Press,
they use post types for forums, and topics and reply’s. A topic, or a
thread, has as its parent a forum, it belongs inside a forum. A reply has
as its parent, a topic. Each of those post types in BB Press are related in
that same manner.
Another plug-in I’ve done some work in is WooCommerce. It has products as a
post type. They also have product variations as a subordinate post type
under that. If you’ve got a particular shirt that you want to sell, maybe
it has a SKU number, but then you have different variations, you maybe have
it in small, medium, large, or red, or blue. All those variations,
WooCommerce creates a separate post type for those variations.
For each variation you want to track different data, like how many you have
in stock, and sometimes even have a different price. They have separate
posts as that.
Now, if you look at, like I said, there isn’t an easy way in the API to
create this relationship, the data base supports it, but you can’t easily
register that relationship. All these plug-ins do some pretty sophisticated
What I’m going to do, is I’m going to walk you through an example of a site
I built, this is a custom plug-in, it’s not released, it’s very specific
for the site that I built it that uses this relationship. I’ll show you
some hooks and filters you can use through the WordPress, actually using
WordPress’s API’s to create this relationship.
The example I’m going to use is a non-profit site that I built. I built for
the Mythapedia Society. It’s a non-profit organization devoted to fantasy
literature and mythology. Actually, their annual conference is here in San
Francisco this same weekend. I’m here for work in San Francisco and Myth
Con at the same time.
The society has groups, discussion groups, across the country, and each
group has multiple meetings. So each meeting, that will be a post type, and
it will belong to an individual group. You start off by registering the two
post types, you register groups, and meetings. As you can see, it adds the
interface for groups and meetings there just by calling that Word Press
function. But there’s no way to tell at this point that they’re related, as
one subordinate to the other.
The next thing I did was use WordPress’s add submenu page hook to inject
some other pages there below the group. I added a meetings page, and then I
added a link to the all meetings and to the “add a meeting” page. Because
meetings are very subordinate to groups, I want to be able to only manage
groups and then manage meetings within that. I also called the remove menu
page hook in order to remove the meetings item from the navigation.
For the rest of this I’m going to show you a short video that walks you
through how the interface works, and then we’ll talk about each thing step-
You can edit a group, and then there’s a meetings meta box there on the
page. You can add a meeting from the group’s page, it launches a lightbox,
you can type in the title, a description for the meeting, even pick a
meeting date here using a java script date picker. You can save the
meeting, it closes the box, and it saves the meeting to that list of
You can add another meeting here, just like this. When you do this, it
creates a meeting post, and when you do this you can also edit existing
meetings. You can pop that up, you can change the date on that for example.
Or you can even trash it here, and if you trash it, it will remove it from
that list of meetings.
If you are a developer, hopefully you can follow along with the different
function hooks. Oh yeah, and we’re going to show, it does create a meeting,
there’s the title, and there’s the description. It uses the meeting date
custom field to store that date relationship.
If you are a developer, hopefully you can get some ideas from the code. The
code will be available for download, like I said.
If you’re not a developer though, hopefully that will inspire you as we
walk through the kinds of different things that people can do with
WordPress. To get the meta box on there, I use WordPress’s add meta box
hook. You can write your own function that will generate any code that you
want to generate here. I injected a list of meetings and an “add meeting”
To get the rest of meeting, I use the query post function. I tell it I want
all the meetings that are a post type of meetings, and have this particular
group as a parent. For the “add meeting” button, it’s just a link.
WordPress uses a library called “thickbox” to handle those lightbox
effects. If you just add a class to your link in the admin area, it will
launch whatever the link is in iframe. When you click those, it will launch
A lot of the heavy lifting for this code is done here, in this custom php
file. I pass it a few parameters. It loads it up in an iframe. I tell it
what the post type is I want to create, and what the post parent is. From
there, if I’m editing one, I pass in a post ID and it will pull up the
existing one. If I don’t pass a post ID, it will add a new one.
On the “saved” or the “move to trash” buttons, both reload the page and
call either WP insert post, and this is where you establish the post. So
when you create the new meeting here, you pass in what the post type should
be and what the post parent should be. This post doesn’t care what the post
type or the parent is, you just pass in an ID and it will save that
relationship. Same thing with WP trash posts, just call that and it will
trash the post.
The last step is to get the list of meetings back to the group’s page when
you call it. WordPress does this with the media uploader. You upload an
image, you pick it, and it inserts it back into the post. To achieve that
effect, all you need is just a little bit of java script.
On the groups page, you need a function to call. I’ve got a function here
called “list meetings” that I put on the group’s page. You pass it a string
of HTML and it will display that as the meetings. Inside the iframe inside
the custom page, you need another java script function that builds that
You can build the list a number of ways. You can build an Ajax list to the
server to get a list of meetings. I reload the page and do it as dynamic
java script inside PHP.
You get the parent window in a variable, and you call its list meetings
function passing back the HTML that you built in this page. Then, in that
list meeting function you, I just did a little list JQuery to find that
list of meetings, empty it out, and then inject into it the new list of
The TB remove, that’s the thickbox remove. You can just call that function
from the group’s page, and it closes the thickbox. When you’re there,
you’ve got your list of meetings on the page.
If you want to download this code, take a look, I’ve got a plug-in
repository, a subordinate post type helpers, is what I’m calling it. When
you activate the plug-in, it doesn’t really do anything, it just gives you
a function you can use as a developer in your own plug-in. the function,
instead of just calling registered post, you can call it registered sub-
post type. You pass in the post type names, the arguments, and then parent
post type. Then that will handle all the user-interface.
Also, Michael will be speaking about extendible extensions. This one is
extendible, you just inject your own custom fields into it just using all
of its library. It’s just Version 0.1 right now, if you’re interested in
getting this kind of effect to work, I hope you will either use the
helpers, or you’ll take a look at the code and get some ideas.
I’d love to get feedback, and patches, and fixes, and other features. If
you want to contribute on GitHub, you can get it up there. Again, I’m going
to be posting these slides on the website.
They’re actually already up there. At randyhoyte.com/wcsf. You can get
those or you can get the code from that link, or from over in GitHub.
Yes, that’s it. We have a few minutes for questions. Any questions,
comments, feedback? Anything else? There’s one right there.
Audience member: This was specific to a one too many relationship, is
there, do you use any custom taxonomy? I’ll give you a little bit more
specific question. I ran into an issue where we needed to have a taxonomy
available to relay numerous custom post types together, but we also had to
have very specific meta associated with those taxonomies.
We decided to actually create a post type that basically mirrored our
existing taxonomies. I’m not sure if that’s doing it wrong, or what, but
would you speak to that, and what maybe your thoughts are on that?
Randy: Yes, and I talked with John from BB Press about this. He had some, a
similar issue. He said that if he could have done custom fields on a
taxonomy, he may have done the forums as a taxonomy, instead of a post
type. Right now in WordPress you can’t store custom fields on a taxonomy
term. There’s nothing wrong with creating a taxonomy and then creating a
related post. A number of people recommend that, it’s very tricky to keep
it in sync.
What you might want to do instead is just keep it as a custom post type
instead of a taxonomy so that you can get those relationships. The trouble
there is that when you do that, you don’t get all the different pages, the
URLs built by WordPress by default. Trying to get that, if your use cases,
you need custom fields on a taxonomy, you do have to kind of work around
the system. The way you’ve done it is one way you might do it.
Your first question, this example is very specific to a one-to-many
relationship. The guy who works on Pods, Scott Clark, is a friend of mine,
and he’s wanting to do something similar with that lightbox approach for
many-to-many relationships which can work really well.
If you’re editing a movie you, can add new actors through a similar
approach. If you’re on actor page, you can add movies in the same way.
Do you have another question?
Audience member: Just to follow up with that, I haven’t used Pods
specifically, but I have used Scribu’s post-to-post plug-in on several
sites. For creating those types of relationships, it is an extremely
valuable tool. Obviously, taxonomies are very helpful, but if you need to
create that contextual relationships back and forth, it’s very good for
Randy: Yes. The one thing that I wish I did, is when you’re editing a group
page, you can’t add a meeting. Right? You can only relate existing meetings
to a group.
Oh, you can, OK. Excellent, yes, that’s a very good plug-in. Okay.
Host: Thank you very much Randy. Round of applause.