Using get_posts to dynamically create columnar markup

The Context

Building a responsive site with wordpress.

The Problem

I have a loop that spits out posts. the site must be responsive. I must use markup to designate columns. However, simply taking the loop content and wrapping it in a div isn’t good enough. I need to intersperse the output of a loop with columnar markup. Say I want two columns, and I must divide the posts between two columns. I’ll have to “inject” markup into my loop output to create my ideal section of code. I could do this with js. But that’d kinda suck. I mean, I wouldn’t hold it against a dev to take the js approach. But I grimace at the thought.

A Hypothetical Solution

Lets get the loop content and put it into an array. Then we’ll split the original array into two “blocks”. We will then print these blocks, wrapping markup around them. That markup will be then targeted by CSS to create columns when the viewport width hits a target breakpoint.

Getting The Loop As An Array

Thanks to the magic powers of google I discovered get_posts. The first sentence of the doc tells us that we are on the right track: “The most appropriate use for get_posts is to create an array of posts…”. That’s great! From that point I can manipulate the array and do what I want. Here is where we can start.

 $args= array( 'post_type' => 'my_cpt' ) ;
 $posts_array = get_posts($args) ;

An Awesome Discovery

It turns out that putting the post output into an array gives us a lot of control over how we choose to publish the posts that we got. Most of the time a mixure of template tags and markup will do what we want. But with get_posts we can replace the usual approach with… anything we want.

If we know some basic PHP then we have a lot more control. Specifically, it helps to know how to do really basic object and array manipulation.

The logic I wanted to impliment was this:

For each post: for two particular custom fields: wrap the custom field in my markup.

And this is how I did it:

foreach ($posts_array as $o ) {
 // get the meta array for the current post
 $meta = get_post_meta( $o->ID ) ;
// get the quote
 echo "<blockquote><p>" . $meta['_cmb_testimonial_text']['0'] . "</p></blockquote>" ;
 // get the attribution
 echo "<p class='attribution'>" . $meta['_cmb_attribution']['0'] . "</p>" ;
 }

Viola! Post content! Now to generate my columnar markup!

Lets take the array, split it into two other arrays, and wrap the two output arrays in markup…

/*
 * how many posts do we put in the first column
 */
 $els = count($posts_array) ;
 $half = round(($els / 2 ));
$arrOne = array_slice($posts_array, 0, $half ) ;
 $arrTwo = array_slice($posts_array, $half) ;
/**
 * output first half of our testimonials
 */
?>
 <div id="stb-testimonials" class="group">
 <div class="testimonial-col col1">
 <?php
 foreach ($arrOne as $o ) {
 // get the meta array for the current post
 $meta = get_post_meta( $o->ID ) ;
 // get the quote
 echo "<blockquote><p>" . $meta['_cmb_testimonial_text']['0'] . "</p></blockquote>" ;
 // get the attribution
 echo "<p class='attribution'>" . $meta['_cmb_attribution']['0'] . "</p>" ;
 }
 ?>
 </div> <!-- ENDS testimonial-col col1 -->
 <?php
 /**
 * output second half of our testimonials
 */
 ?>
 <div class="testimonial-col col2">
 <?php
 foreach ($arrTwo as $o ) {
 // get the meta array for the current post
 $meta = get_post_meta( $o->ID ) ;
 // get the quote
 echo "<blockquote><p>" . $meta['_cmb_testimonial_text']['0'] . "</p></blockquote>" ;
 // get the attribution
 echo "<p class='attribution'>" . $meta['_cmb_attribution']['0'] . "</p>" ;
 }
 ?>
 </div> <!-- ENDS testimonial-col col2 -->
 </div>
<?php
}

Done.

The complete chunk of code is here. It’s part of a bundle of files that constitutes a plugin for publishing testimonials, and is in use on the Stalking The Boogeyman website. (I’m helping to maintain this beautiful site, which was built by Chris Van Patten for DRT Advertising). If anyone actually wants the full plugin, just ask me and I’ll put it on github.

No comments yet.

Leave a Reply

%d bloggers like this: