(My first WP question ever asked! Be gentle!)
I’m building a site that is mostly pages (i.e., static), using WP as CMS. At the bottom of several of the pages, there will appear 1, 2, or 3 “promo boxes” — basically button-images that link to other parts of the site. Though only up to 3 promo boxes will appear on any given page, there will be ~30 different ones to choose from.
When my client creates a new page, I’d like him to be able to choose promo boxes from something like a dropdown list of all of the possible promo boxes.
Seems to me this should work like this:
- Create a custom post type called “promo-box”. (Though it could just as easily be a tag for regular posts.)
- Use a tool like Custom Field Template to create a dropdown on the page editor, where the values of the dropdown options are dynamically generated from the list of all existing promo-box posts. (This is the part I don’t know how to do.)
- Access the resulting metadata (post number is really all I need, then I can get everything else) on the page template.
Based on responses to other questions here, I have taken initial looks at WPAlchemy MetaBox, Posts-2-Posts, and SLT Custom Fields, but I confess the documentation for each of them is slightly geekier than I am, so I haven’t delved too deeply.
Advice? Is one of the above tools the right solution for me, and I just have to figure it out? Am I missing something here?
As the author of WPAlchemy, I’m a bit bias, but you essentially have a good working model outlined to follow depending on what ever route you choose.
However, if using WPAlchemy, you would basically do something like the following (step #2):
custom/meta.css
can contain styles that you can style your form with andcustom/meta.php
is essentially an HTML file with the FORM contents of the meta box, in this case your drop down, to generate your drop down you would do a custom wp query to get all your custom post types. WPAlchemy has some special helper functions to aid in creating your form elements.There is additional documentation to assist you when working in the template.
The main goal of WPAlchemy was to keep control in the hands of the developer, from styling (look + feel) to meta box content definition.
And myself and others are always willing to help those who comment and ask questions.
Hehe, you’re a newbie! We’re gonna rip ya to shreds…!
j/k 🙂 We offer warm welcome to all newbies here, glad to have you.
So this is the 3rd time I’ve heard this requirement, twice from clients and not again from you (and your client.) That tells me it’s a reasonably common need.
I liked your analysis so I decided to code up a class to address your 2nd point. I called it
LittlePromoBoxes
because I can never get this song out of my head, thanks to them. Basically I use the class to encapsulate to otherwise avoid potential naming conflicts with the functions I’d need to write.You can put this class in your theme’s
functions.php
file or in a .PHP file of a plugin you might be writing (but don’t worry, it looks a lot more complex than it is.)The first function
on_load()
is a static function which I call at the end of the class declaration to initialize the three (3) hooks you’ll need (fyi static functions are essentially functions related to the class, not the instance) :The
init
hook to register thepromo-box
post type,The
add_meta_boxes_post
hook to allow you to define the metabox, andThe
wp_insert_post_data
hook to allow you to capture the selected promo boxes and save to the database.Each of those hooks reference another static function in the class (these were the functions I was encapsulating by creating the class.)
I’ll skip describing the
action_init()
function and mymake_labels()
helper function assuming you know how to register a post type based on you question.The
action_add_meta_boxes_post()
function registers the metabox using the WordPress core functionadd_meta_box()
and I’ve commented it’s parameters to explain why I passed what I passed for each. The callback functionthe_little_promo_boxes_metabox()
is of course another static function of the class and it is what actually displays the content in the metabox. It primarily uses the WordPress core functionwp_dropdown_pages()
to display a list of promo boxes (note that it will display other post types besides ‘page’ but only if they are marked as being'hierarchical'=>true
in their post type registration. Why only hierarchical? Because that’s the way they wrote it, that’s why! 🙂Since we’re showing three (3) dropdowns we need to give each a unique ID in the HTML (
"promo_box_{$i}"
) but the same name with square brackets ('promo_boxes[]'
) so that PHP will collect them into an array inside$_POST
variable (which WordPress accesses for us; you’ll see how in a minute). And of course we need to set the selected value ((empty($promo_boxes[$i]) ? 0 : $promo_boxes[$i])
) if indeed one of the values had previously been selected.I also used the WordPress core function
get_post_type_object()
to show how to get the labels from a post type, and also using the WordPress core functionget_post_meta()
to retrieve an array of promo box IDs from using the custom field key ‘_promo_boxes’ which I’ll show you have to save next (note I used a preceding underscore in the name'_promo_boxes'
which causes WordPress to hide from the standard custom field UI when the user is editing the post.).The last function to describe before you see the code is
filter_wp_insert_post_data()
which receives the existing post data in the first parameter ($data
) and the contents of the$_POST
array thanks to WordPress as the second parameter ($postarr
). Inside this function we call the WordPress core functionupdate_post_meta()
and extract the promo boxes array ($postarr['promo_boxes']
) to save to the custom field value for the key'_promo_boxes'
for the post specified by the$_POST
array (i.e.$postarr['ID']
).That said, here’s the code for the
LittlePromoBoxes
class:There are still two (2) static functions not yet mentioned:
get_promo_boxes()
andget_promo_box()
; these are helper functions to help you retrieve the posts ofpost_type='promo-box'
by their ordinal numbers 1..3. But to make them more WordPress like here are two wrapper functions to add to your theme’sfunctions.php
file (note that you can pass a post as a parameter but you don’t have to unless you are using a different post that the one in The Loop):Now you can call one or both of these functions in your
single.php
theme file with code that might look like this (this code could have been written in a loop but most WordPress themers seem to like to duplicate code so they can read it instead of eliminating redundancy. So, when in Rome…):