Last updated August 7th, 2015 at 10:17 am
Eaton Academy’s Web site (EatonAcademy.org) is just one of many hybrid projects I’ve built over the years. Namely, the main section of site is custom-built using generous doses of PHP and MySQL for templating while the blog section is built on WordPress. The two sections are visually integrated but fundamentally independent from a functional standpoint.
When Eaton co-founder Brian Uitvlugt wanted me to implement an emergency announcement banner that would appear at the top of all pages of the site (for school closing information and such), he was issuing an interesting and fun challenge.
One option would have been to extend the functionality of the already-existing custom (non-WordPress) Intranet system. I could have added a form through which Brian and other authorized users could add, edit, and delete the notices (along with associated database modifications to store and serve the information). Then I could customize both the main site’s templates and the blog’s templates to display the notices to the public.
Instead, I suggested (and Brian agreed) that we leverage WordPress for the job.
The end result
We launched the banner feature in December of 2012, in anticipation of school closings, late openings, or early dismissals due to extreme weather.
I had almost forgotten about the little-used feature (as had Brian) until today — when the school’s email system went down. Here’s what the Web site looks like at the time of this writing.
Banner on Main Site

Banner Announcement on index page of blog

Banner Announcement on single page of blog

Functional Specs
Here’s the general approach we took.
- We agreed to create a special new WordPress post category called “Banner”. A blog post MUST be assigned to the “Banner” category to be used in the site’s banner.
- Only the MOST RECENT blog post assigned to the “Banner” category will be used in the banner.
- Optionally, the post should be marked as a STICKY post. This will ensure that it appears as the first post in the blog’s main index page, even if another post has a more recent publication date.
- To remove a banner from the public-facing Web site, an authorized user would perform one of the following actions in the WordPress dashboard:
- delete the post
- change the post’s STATUS to ‘Draft’ or ‘Pending Review’
- change the post’s VISIBILITY to ‘Password Protected’ or ‘Private’
Technical Specs
For the techies in the audience, here are some details of how I put the nuts and bolts together. I’m not going to get heavy into explaining the code because (a) you might not care or (b) you might be able to figure it out yourselves. If you do wonder why I’m doing what I’m doing (or if you have a better way), please feel free to post in the comments, and I’ll be happy to respond.
Function to get post data array
Since I’m working outside of WordPress, I couldn’t use WordPress’ internal query methods to grab the post data. Hence the multi-table SQL query code with a fairly involved “where” clause involving the wp_terms, wp_term_taxonomy, and wp_term_relationships tables.
This function (get_blog_posts_recent()) gets and returns a nested array of posts that meet the selection criteria passed in a single line of code in the header template of the main site (keep reading for that).
function get_blog_posts_recent($args=array()) { $defaults = array( 'table' => 'wp_posts', 'fields' => array('ID', 'post_title', 'post_date', 'guid'), 'category' => '', 'limit' => '1' ); $r = array_merge($defaults, $args); extract($r); // When category is specified: if ( !empty($category) ) { $new_fields = array(); for ( $i=0, $n=count($fields); $i<$n; $i++ ) { $new_fields[] = 't1.' . $fields[$i]; } $field_list = implode(', ', $new_fields); $sql = "select " . $field_list . ", t3.name from " . $table . " as t1, wp_term_relationships as t2, wp_terms as t3, wp_term_taxonomy as t4 where t1.post_status = 'publish' and t1.post_type = 'post' and t1.ID = t2.object_id and t2.term_taxonomy_id = t4.term_taxonomy_id and t4.term_id = '$category' and t3.term_id = '$category' order by t1.post_date desc limit $limit"; } else { // ANY category: $field_list = implode(', ', $fields); $sql = "SELECT " . $field_list . " FROM " . $table . " where post_status = 'publish' and post_type = 'post' order by post_date desc limit $limit"; } $result = mysql_query($sql); if ( !mysql_num_rows($result) ) return false; // Else... $data = array(); while ( $record = mysql_fetch_assoc($result) ) { $data[] = $record; } return $data; }
[PS/Update for fellow geeks: I just finished reading Andrew Nacin’s recent post at Make WordPress Core entitled Potential roadmap for taxonomy meta and post relationships. If the ideas in that post are implemented (especially the elimination of the wp_terms table), that multi-table join in the code above could be simplfied considerably. We can hope…]
Is there a post that matches the selection criteria?
This function (eaton_banner_exists()) calls the one above. If there’s no post whose category id is associated with the passed category id, then we can just quit (the good old return false (line 10). Otherwise, go get it or them.
function eaton_banner_exists($category, $limit, $fields) { $conn_link = banner_conn(); if ( $data = get_blog_posts_recent( array ('category' => $category, 'limit' => $limit, 'fields' => $fields ) ) ) { mysql_close($conn_link); include(SITE_INCLUDES_PATH . 'dbconn.php'); return $data; } else { mysql_close($conn_link); include(SITE_INCLUDES_PATH . 'dbconn.php'); return false; } }
Function that looks for the most recent banner post
This function (eaton_banner()) uses the hard-coded category id that corresponds to “Banner” (’56’) and specifies a limit of 1 post to grab. It also passes an array of field names to be selected in the eaton_banner_exists() function.
function eaton_banner( $category_id = '56', $limit = '1' ) { $fields = array('ID', 'post_title', 'post_date', 'guid', 'post_content'); if ( $data = eaton_banner_exists( $category_id, $limit, $fields ) ) { //echo_r($data, 'Banner test'); return $data; } else { return false; } }
The one-line call in the main site’s header template
I added this one-line script to the header template. If the eaton_banner() function finds and returns a post in the “Banner” category, then we’ll include a simple file at the top of the page. Otherwise, we’ll do nothing.
<?php if ( $banner_content = eaton_banner() ) include(SITE_INCLUDES_PATH . 'inc_banner.php'); ?>
Finally, the include file for the main section of the site
This is the simple HTML (with a little bit of interspersed PHP) that makes the banner display, if it indeed exists. Some CSS markup makes the banner appear inside a centered, bordered box at the very top of each page of the main site.
<?php extract($banner_content[0]); ?> <div class="eaton-banner"> <div class="inner"> <h1><?php echo $post_title;?></h1> <div class="text"> <?php echo nl2br($post_content);?> </div> </div><!-- .inner --> </div><!-- .eaton-banner -->
Conclusion
If the Eaton Web site were completely built on WordPress, adding an announcement banner to all pages of the site would have been extremely simple. I probably would have used a plugin like iTheme’s Boom Bar.
But a hybrid Web site needn’t pose insurmountable obstacles. With a little bit of mental elbow grease — and just the right amount of knowledge of PHP, MySQL, and the WordPress database structure, one can accomplish all kinds of nifty things.
Leave a Reply