Using WordPress Pods to Manage Custom Data

Last week I posted about relating a WordPress post to your Pods data. But I realize, for a lot of people, the question is still: Why use Pods to manage your custom data in the first place?

There are a ton of benefits to using PodsCMS. Here’s a thread worth reading on the forum. But I thought it might be helpful to see an example.

Let’s go back to our related books tutorial. Why couldn’t we do this using custom fields and custom post types? That would be simple enough. We’d first create a post type called “books”. Then we’d need to create a meta box that would add the post ID of the related book to our post.

No big deal. We could easily query the related books lik so (I am not testing this code, so don’t try and reuse. This is purely for example):

$bookid = get_post_meta($post->ID,'related_books', false); 
$args = array('post__in' => $bookid, 'post_type' => 'books');
$books = new WP_query($args);

Then of course, we’d use a while loop:

while($books->have_posts()) : $books->the_post();

Pretty simple. But what happens when we start adding complexity? What if we want to feature books that are either related by ID, or have a certain author?

Let’s assume for the moment that we’re using a custom field to save the author name in the books post type. This scenario is a little more challenging. The query above is restrictive to books that have been selected as related. But since we want to do an “OR” query we’re probably going to need a custom select query:

global $wpdb;
$id = $post->ID; //the current post id
$query = "SELECT DISTINCT p.ID FROM wp_posts p INNER JOIN wp_postmeta AS m ON p.ID =  m.post_id WHERE p.post_type = 'books' AND p.post_status = 'publish' AND ( (m.meta_key = 'book_author' AND m.meta_value = 'William Shakespeare') OR p.ID IN(SELECT DISTINCT meta_value FROM wp_postmeta WHERE meta_key = 'related_book' AND post_id = '$id') )";
$results = $wpdb->get_col($query); 

In theory this custom select query gets us an array of post IDs we can then pass on to the standard WP query using the post__in argument we used above. Notice that just a modest increase in the complexity of the request leads to major increase in the complexity of the query.

But what if we are using a post_type for authors and need all the authors who have written certain kinds of books. Say we have a category “childrens books” and we want to get a list of all authors who have written a children’s book. This is where WordPress starts to get pretty convoluted. We could use a custom select query, like we did before. But we could also combine some WP queries.

//get the books in the childrens book category
$cbooks = get_posts('post_type=books&category_name=Childrens Books');
foreach($cbooks as $cbook) {
  $cids[] = $cbook->ID;
}
$authors = query_posts(array('post_type'=>'author','post__in'=>$cids)); 
?>

This is a a pretty inefficient use of code and it only get worse. Imagine needing to see a list of books in a certain category, with a certain author, with a certain number of pages, that was written in 2010.

You’re using custom fields for the publication year and the pages, a custom post_type for author and a category for the genre. Think of the mental power that will go into putting this query together. You’ll have to do a custom select query.

global $wpdb;
$query = "
SELECT DISTINCT ID FROM wp_posts p
INNER JOIN wp_term_relationships AS tr ON tr.object_id = p.ID
INNER JOIN wp_term_taxonomy AS tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
INNER JOIN wp_terms AS t ON t.term_id = tt.term_id
INNER JOIN wp_postmeta AS m1 ON m1.post_id = p.ID AND m1.meta_key = 'related_author'
INNER JOIN wp_postmeta AS m2 ON m2.post_id = m1.post_id AND m2.meta_key = 'publication_year'
INNER JOIN wp_postmeta AS m3 ON m3.post_id = m2.post_id AND m3.meta_key = 'num_pages'
WHERE p.post_status = 'publish' AND p.post_type = 'books'
AND t.slug = 'childrens-books' 
AND m1.meta_value = 'William Shakespeare'
AND m2.meta_value = '2010'
AND m3.meta_value > 200
ORDER BY p.post_title ASC
";
$results = $wpdb->get_col($query);
query_posts(array('post__in'=>$results)); 

I’m not even sure if this query would work, but the query that would work would look a lot like this.

So you get the point. WordPress has no method of simplifying complex queries.

If you are the client and know exactly how you plan to use your site then this isn’t such a big worry. But if you’re a developer working for a client using WordPress as a CMS, you don’t know what the client might eventually request. Nevertheless, it’s your job to be able to meet that request.

Pods is a CMS framework built specifically to deal with these complexities. Let’s perform the query above using the Pods approach.

$pod = new Pod('books');
$pod->findRecords('name ASC',-1, "author.name = 'William Shakespeare' AND t.year = '2010' AND t.pages > 200 AND cat.slug = 'childrens-books'"); 
echo $pod->showTemplate('book_list');

Seriously, that’s it. And of course, you could substitute “OR” for any of the “AND” operators above to get a more inclusive result.

Pods gets a lot of criticism for being a WordPress hack. If you can do what you want to do with WordPress why introduce an unnecessary plugin? I hope I’ve demonstrated here that the advantages to using the PodsCMS Framework are enormous in terms of time and mental energy saved.

And it’s key to remember that Pods is a development Framework, not really a plugin. It can be used to manage minor amounts of custom data in your WordPress posts or a complex web of related content types that are outside of the Posts system altogether.