What is Pods?

I have written about Pods before, but I decided to rewrite and combine all the info I have gathered on using it, into one concise post. It will probably be ongoing, whenever I learn a new way to do things with it. This post assumes you know what post types are and what a custom field is, as pertaining to WordPress.

If you are used to using pods and want to see some queries using the ‘where’ clause, scroll down to here.

Among all the plugins I use, Pods has to be one of the top ones. It is simply a must for me when it comes to building complex websites. Pods has such incredible abilities and I have only begun to scratch the surface with it.

Pods is a plugin, or better, a framework, that allows you to create more post types and custom fields for those post types. Those fields can be extremely simple, like a text field, or a number field, or very complex, like a relationship field. Below is a screenshot of a post type called ‘invoice’. I have added special fields to the invoice post type, all with one plugin. Pods.
(Click images to Enlarge)

Above I used the Pod Admin to create the new post type. With Pods, the new post type can sometimes be referred to as a ‘Pod’. This new pod is added to the sidebar. Then I added custom fields to that pod (sometimes called pod fields). On the right you can see what the new posts (or pod items) under invoice will look like. Below the editor, you can see the ‘More Fields’, section that pods creates.

Some plugins only create post types, others just create custom fields. Then there are some that do both in a convoluted and bloated way. Trust me, I have used many of them… Pods is absolutely the best plugin of its kind.

Showing the custom fields

You can show most of custom fields with the typical get_post_meta() function. By passing the field name I created in the Pods admin area, and the ID of the post, I can get the custom field and do whatever I want with it. Below I echo out the ‘Invoice ID’ of my invoice example.

//above I created a field called invoice_id. Lets call it.
//assuming I am in the loop and have access to get_the_ID()

echo get_post_meta(get_the_ID(), 'invoice_id', true);

Getting the fields using pods

Sometimes you will want to show the field using pods. This might be because you made a special field that wont show right with get_post_meta(). Pods requires you to first get the pod item (post) you need, then you can get any fields from it with some special pod functions.


The pods() function will get a pod item or items depending on what the second parameter is. The first parameter simply takes the name of the post type we want. In my example, ‘invoice’. (Although I probably should have used a prefix in the name so it doesn’t ever get confused with a plugin I may install.)

The second parameter can take an ID and it will get just the one pod item (post). Later, hopefully well discuss what else this parameter can take, making pods really powerful. Once we get the pod item, we save it to a variable as an object. Now we can get all different fields from this pod. Of course make sure there is a post that got found by using exists().

//First we get the pod item with pods()

$pod = pods('invoice', get_the_ID() );

//getting the pod fields for one pod
if( $pod->exists() ){
  echo $pod->field('invoice_id');

field() and display()

These two are member functions that can be called on your $pod object which you created. The field() will show you what get_post_meta() will usually show you for a simple field. So there is no need to get your pod to call a simple field, when get_post_meta() can be used. For more complex fields, like a file upload, or a relationship field, field() will return an array.

That’s where display() comes in. This will show you what you normally expect to get when trying to show a complex field, like an upload field. For an upload field, it will return the url, as opposed to an array. For a relationship field, it will return a comma separated list. Display also affects other fields, like the currency field, and can be used to show a number with the right currency symbol in front.

Whenever you’r trying to show the value of a field and it doesn’t look right with field() , just try using display() before resorting to manipulating the value further.


This is a good function to know, one I use often, so I felt it needed special mention. When creating an upload field, both field() and get_post_meta() will return an array, when you try to output it. (The array does hold ‘guid’ which has a path to the url, but I don’t think thats the right way to get it.)

Normally you would need to get the pod for this post as shown above and then use
$pod->display('image_field'); to get the image url. With pods_image_url, you can get the url without having to get the pod. Simply call the following in your loop:

echo pods_image_url( get_post_meta(get_the_ID(), 'upload_field_name', true) );

That will get the url easily and you can echo that in an image tag or href or wherever you need. I use this often when allowing a post type to have extra images attached and want to show them in my theme.

Getting multiple pod items

You can get more than one pod item by giving pods() an array instead of an ID as the second parameter. This array will allow you to filter the pods to find the ones you want. Below I use the array to get the first 2 pod items of post type ‘invoice’.


$invoices = pods('invioce', array(
    'limit'=> 2

if ( 0 < $invoices->total() ) { 
        while ( $invoices->fetch() ) {
          echo get_post_meta($invoices->ID(), 'field_name', true);
          echo $invoices->field('field_name');


The array is actually a short hand for calling the function find() . This is one of the most important functions in Pods. Make sure to visit the link to the documentation for find() . It has a great video and most of all a table at the bottom which can be used when making a query. Hopefully we will get back to this once we learn more about relationship fields.


Relationship Fields

Now were getting to the meat of Pods. Here is where Pods truly shines. You can create a field that has a value that points to another post. This basically connects 2 posts together. It can be from the same post type or a different one.

So lets say I had a post type ‘animals’. This post type has fields for the animal, like where it’s found, what the species is called, and what zoo they can be seen at. Then I have another post type called ‘zoo’. This one has fields for where the zoo is located, what its name is, how big it is and, what animals are found there.

As you can see I have a post type zoo’s and a post type animal’s and they relate at the italic fields. Under ‘animals’ a zoo field can be created as a relationship field that points to zoo. This field will be populated with a list of all posts found under post type ‘zoo’. So if I make 5 Zoo’s under the post type ‘zoo’,  they should be available for me to choose under the zoo field on a post type animal. I can choose one of those 5 as my value for the custom field under animals.

Here I made the field ‘zoo’ for animals. I made it a relationship field and have it related to the post type Zoo. Notice in the second image I have both post types in the sidebar. In the second image I chose to select New York as the related Zoo. This means I have a post called ‘New York’ under the post type Zoo.

The same could be said with post type ‘zoo’. I could have a field that points to the animals. Even better I can make this a multiple select relationship field and, I can have many animals at one zoo. This would be called a 1-to-many relationship. Because the animals can only be in one zoo, while a zoo can have many animals. Of course I could change that and make it many-to-many. Below is an image of me using a many-to-many relationship field, as I choose two Zoo’s under my animal post.

You can set a relationship field to have single or multiple select capabilities under the fields ‘Additional Field Options’ tab in Pods admin.


Bi-Directional Relationship field

When one relationship field points to a post type and that post type has a relationship field pointing back, they can become a bi-directional relationship. This means they are connected on a deeper level. If I add a zoo to an animal post, that zoo automatically also adds that animal to its relationship field, on its end. So both posts are updated with their respected values when one side gets changed. It’s very cool if you ask me! So if I save the post above, the Bronx Zoo as well as New York’s will get a new animal in it’s animal field.
You can read more here about relationship fields:



Getting Relationship Fields

This time you definitely want to use pods, as get_post_meta is not as powerful. Basically the field() function will return an array of pod items from the relating post type. You can then go through these pod items and do what you want with them.

//getting one pod item
$pod = pods('animals', get_the_ID() );

//make sure it exists
if( $pod->exists() ){

  //get the related zoo's field and store it in a var
  $related = $pod->field('related_zoos');

  //check if the field is empty. If not lets show some of the zoos!
  if ( ! empty( $related ) ) {
   foreach ( $related as $rel ) { 
     //$rel is an array of one pod item
      echo get_the_title( $rel['ID'] );

Here I am getting the zoos that are connected to this animal. Then I am going through each of them and echoing out each zoo’s name. I find the most important piece of info is the related ID’s. With those you can do everything.

Getting related ID’s easier

I don’t usually need all the stuff that comes with the related posts. An array of ID’s is usually simpler to work with for me. Here is a little trick to get the related ID’s as opposed to all of the stuff.

//getting one pod item same as before
$pod = pods('animals', get_the_ID() );

//make sure it exists
if( $pod->exists() ){

 //get related ID's
 $related = $pod->field('related_zoos.ID');

 //check if the field is empty. If not lets show some of the zoos!
//NOTE: foreach loop only needed if the relationship field is  multi-select
 if ( ! empty( $related ) ) {
   foreach ( $related as $id ) { 
     echo get_the_title($id);

Above I have changed the field function to field('related_zoos.ID') which gets the ID’s only. Now when I make a for each loop, I’m looping through simply ID’s and nothing else. Pretty nifty. You can fine tune the field function to get a list of anything in those posts!

In fact the field() function can take a string that traverses through the tables and gets anything! I can do field('related_zoos.zoo_location') to get a list of zoo locations from each zoo related to this animal!

Relationship Field Notes

So using relationship fields is awesome. It is so powerful and being able to string together fields to get what you want is amazing! but there are some things to be aware of.

Multiple Select vs. Single Select

If the relationship field is a single select it will return one array with one pod item. This means you don’t need to loop through an array to get the ID. You already have it.

If you choose to get all related ID’s, as I did above, field('related_pod.ID') you will only get one back, with no array and a foreach() loop will not work! Just make sure the field returns something with if( ! empty() ) and then use the ID.

With multiple select, an array of arrays is returned (array of posts) always.
So even if you use field('related_pod.ID') , and the post has been related to one item only so far, you will still need a foreach loop to get the ID as in the code examples above.

This is why its good to use var_dump() or print_r() to see exactly what you are getting back when things aren’t wokring the way you expected.

Filtering for the right Pods

Now we are ready to start scratching the surface! Time to start using pods to query for the exact pods we want. At some point you will find yourself wanting to get all posts that have a certain relationship field, or something similar to that. Here is where the find() function comes back into play.


Find is like WP_Query and can be used in a few ways. You can look it up here and see how it works. There is even a long video showing you various ways of using it. Basically you can call it on a pod item after you get it using pods(). Or you can pass pods() an array and this is my preferred method.

$pods = pods('post_type', array(
    'limit' => 15,
     'page' => 2,

The array above will runt he find and query for 15 posts and get the second page of results. It’s just like WP_Query. Whats really cool is when you need to find posts where a relationship exists or equals something.

Using ‘Where’

This means if I want all Zoo’s where a certain animal exists, I can get all those using where. Below I am on a single animal post. I get the current ID and search for all Zoo’s where this animal is and output all the Zoo’s where it is found:

$current_animal = get_the_ID();

$zoos = pods('zoos', array(
  'where' => 'related_animals.ID = " ' . $current_animal . ' " '
) );

//showing them
if ( is_object( $zoos ) && 0 < $zoos->total() ) {
 while ($zoos->fetch()) {
   $pod_id = $zoos->ID();
   echo '<p>' . get_the_title($pod_id) . '</p>';


Now you can see the power of relationship fields. You can use them to get the right content. The where clause can be used to make very powerful queries. Let’s see more examples.

Where with a basic custom field

$zoos = pods('zoos', array(
 'where' => 'zoo_text_field.meta_value = "some text" '
) );

For a basic field thats not complex, you will want to use field-name.meta_value. Here I had a basic custom field of text. But a website or any text based field would have worked.

Where with a number or yes/no field

$zoos = pods('zoos', array(
 'where' => 'zoo_available.meta_value = 1'
) );

The only difference is that the field it equals has no quotes around it. So this will only show zoos that have a checkmark next to zoos available. (assuming I have a custom field called zoos available)

Where with AND and custom field of related field

So in a way I find this easier than using WP_Query because you are literally writing SQL. And its really easy with the relationship fields. Here we will use AND to make sure and get a zoo thats available AND all related_animals that have a region_found field set to New York. Yes you can traverse through the tables it’s so cool!!

$zoos = pods('zoos', array(
 'where' => 'zoo_available.meta_value = 1 AND
             related_animals.region_found.meta_value = "New York" '
) );

Where a relationship field has at least 2 values found

This is a weird one. I needed to find all pods that had at least 2 fields in a relationship multiple select field. This isn’t typical and I had some help from Scott Kingsley Clark, the maker of Pods. But I’m sure someone else might need it. Here we don’t care what the relation field is. We just care that there are 2.

 $members = pods ( 'zoos', array(
   'having' => 'relationship_count >= 2,
   'select' => 't.*, COUNT( related_animals.ID ) AS relationship_count',
   'groupby' => 't.ID',


Here I am getting all zoos that have at least 2 animals associated with it. I don’t know what the animals are but as long as it has 2 I’m happy.

In Conclusion

As you can see pods is really, really, really cool and what you can do with it is limitless. It is an amazing plugin and this post can go on forever. But I’m scared to make it too long. So there ya go. Everything I know about pods… so far!

2 thoughts on “Playing With Pods

  1. Armando Duran says:

    I am creating a Web Application using Pods and I have been trying to really understand the way to traverse in all the relationships. I saw a video from the Pods guys where Scott does the traversing. But reading this post brought me good clarity.

    Thanks for posting it!

Leave a Reply

Your email address will not be published. Required fields are marked *