Stellar WordPress Portfolio Control with Custom Post / Meta Types
Wordpress 3.0 has introduced a lot of very powerful new features into the theme developer’s toolbox. The most exciting of these is probably the addition of custom post / meta types.
Intro and Prerequisites
We are going to use these features to create a custom “portfolio” post type and add additional options to it using custom metas that will correspond to things like “project URL”, “Client name”, etc.
To define a custom post type, use
register_post_type();
in your functions.php and then customize the post type with a whole slew of options.
Custom metas can be defined with
add_meta_box();
This function also has options.
#1 – Create Custom Post Type
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
add_action('init', 'create_portfolio'); function create_portfolio() { $portfolio_args = array( 'label' => __('Portfolio'), 'singular_label' => __('Portfolio'), 'public' => true, 'show_ui' => true, 'capability_type' => 'post', 'hierarchical' => false, 'rewrite' => true, 'supports' => array('title', 'editor', 'thumbnail') ); register_post_type('portfolio',$portfolio_args); } add_action("admin_init", "add_portfolio"); add_action('save_post', 'update_website_url'); add_action('save_post', 'update_client'); |
This will create our post and tell WordPress to update our custom metas “Website URL” and “Client” when we save the post.
#2 – Add Meta Box
This will add a new write box below your post editor:
1 2 3 |
function add_portfolio(){ add_meta_box("portfolio_details", "Item Details", "portfolio_options", "portfolio", "normal", "low"); } |
#3 – Create Options for Meta Box
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
function portfolio_options(){
global $post;
$custom = get_post_custom($post->ID);
$website_url = $custom["website_url"][0];
$client = $custom["client"][0];
?>
<div class="detail">
<label>Website URL (don't forget <strong>http://</strong>):</label><input name="website_url" value="<?php echo $website_url; ?>" />
</div>
<div class="detail">
<label>client:</label><input name="client" value="<?php echo $client; ?>" />
</div>
<?php
}
function update_website_url(){
global $post;
update_post_meta($post->ID, "website_url", $_POST["website_url"]);
}
function update_client(){
global $post;
update_post_meta($post->ID, "client", $_POST["client"]);
}
add_filter("manage_edit-portfolio_columns", "portfolio_edit_columns");
add_action("manage_posts_custom_column", "portfolio_columns_display");
|
This will add an input box for “Website URL” and “Client”.
#4 – Create Custom Taxonomy
This custom taxonomy is going to function as a “Services Rendered” section that allows the user to select which services were performed for each portfolio item.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
add_action( 'init', 'services_rendered', 0 ); function services_rendered() { register_taxonomy( 'services_rendered', 'portfolio', array( 'hierarchical' => true, 'label' => 'Services Rendered', 'query_var' => true, 'rewrite' => true ) ); } |
#5 – Create Custom Info Columns
The functions below will allow us to customize the data that is displayed in the WordPress admin when browsing the “Portfolio” custom post type items, and also how that data is displayed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
function portfolio_edit_columns($portfolio_columns){ $portfolio_columns = array( "cb" => "<input type=\"checkbox\" />", "title" => "Project Title", "description" => "Description", "url" => "Item URL", "client" => "client", "services" => "services", ); return $portfolio_columns; } function portfolio_columns_display($portfolio_columns){ switch ($portfolio_columns) { case "description": the_excerpt(); break; case "client": $meta = get_post_custom(); echo $meta["client"][0]; break; case "url": $meta = get_post_custom(); echo $meta["website_url"][0]; break; case "services": echo get_the_term_list( $post->ID, 'services_rendered', '<ul><li>','</li><li>','</li></ul>'); break; } } |
#6 – Display Portfolio Items on Portfolio Page
Use this as your loop in your portfolio page template:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?php $loop = new WP_Query(array('post_type' => 'portfolio', 'posts_per_page' => 10)); ?> <?php while ( $loop->have_posts() ) : $loop->the_post(); ?> <div class="portfolio-item"> <h2><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2> <div class="thumbnail"> <?php the_post_thumbnail(); ?> </div> <div class="excerpt"> <?php the_excerpt(); ?> </div> </div> <?php endwhile(); ?> |
# 7 – Display All Data on Single Post Page
Create a new single.php page called single-portfolio.php and add this to it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?php if (have_posts()) : ?> <?php while (have_posts()) : the_post(); ?> <h2><?php the_title(); ?></h2> <?php the_content('Read the rest of this entry »'); ?> <?php $custom = get_post_custom($post->ID); $customer = $custom["client"][0]; $website_url = $custom["website_url"][0]; ?> <div class="details"> <h3>Details</h3> <div>Client: <span><?=$customer?></span></div> <div>URL: <span><a href="<?=$website_url?>"><?=$website_url?></a></span></div> <div class="services"><?php echo get_the_term_list( $post->ID, 'servicesRendered', 'Services Rendered: <ul><li>','</li><li>','</li></ul>' ); ?></div> </div> |
# 8 -Style to Your Heart’s Content
Simple sample:











53 Comments
← Older Comments-
rickj says:
June 9, 2011 at 10:25 am
-
rickj says:
June 9, 2011 at 10:26 am
-
rickj says:
June 9, 2011 at 10:29 am
-
Pippin Williamson says:
June 13, 2011 at 9:02 pm
-
Shane says:
June 18, 2011 at 12:09 pm
-
Pippin Williamson says:
June 20, 2011 at 12:17 am
-
Kim Smith says:
June 27, 2011 at 4:22 pm
-
Pippin Williamson says:
June 29, 2011 at 11:13 am
-
Ingrid says:
August 8, 2011 at 12:11 am
-
Pippin Williamson says:
August 8, 2011 at 9:04 am
-
soulmenj says:
August 9, 2011 at 3:45 am
-
Pippin Williamson says:
August 9, 2011 at 8:18 am
-
soulmenj says:
August 9, 2011 at 7:41 pm
-
Pippin Williamson says:
August 9, 2011 at 8:06 pm
-
soulmenj says:
August 9, 2011 at 8:22 pm
-
soulmenj says:
August 9, 2011 at 11:03 pm
-
Pippin Williamson says:
August 11, 2011 at 9:05 am
-
Alessio says:
September 10, 2011 at 11:36 am
-
Pippin Williamson says:
September 10, 2011 at 12:49 pm
-
soulmenj says:
October 6, 2011 at 2:56 am
-
Pippin Williamson says:
October 6, 2011 at 12:22 pm
-
soulmenj says:
October 6, 2011 at 6:24 pm
-
arifur rahman says:
January 6, 2012 at 7:45 am
← Older CommentsI actually get the same…a blank white page, any help would be great!
I actually get the same, a blank white page, sorry for the dupe but I wanted to get notified of comments…
nevermind, I got it. You’re missing the endwhile in your last one
@rickj – Thanks for noticing that.
I’m surprised no one has pointed this out.
There is an autosave issue with your custom meta boxes.
May want to add that statement in.
@Shane – I need to update all of the code in this tutorial as it is rather out of date now. I will see if I can make the update soon.
Hi Pippin,
You helped me a while back set up my portfolio site using this tutorial. I have a question about what you helped Henry with (Feb. 2011). He was asking you what statement to use to keep the “Launch Website” link from displaying if there was no url in the field. You gave him the code below, however, I can’t figure out where this code goes.
if (!empty($website_url) { echo ‘Launch Website‘; }
In my single-portfolio.php file I have this to display a button to visit the site:
<a href="” target=”blank”>Visit the Site
How do I make this conditional. Currently, even if there is no url in the field, the button will still display. You can visit my site to see how I have the page set up. http://www.blueturtlegraphics.com/portfolio_type/web-design-2/
Any help is much appreciated.
Kim
@Kim – The anchor link tag needs to go in between the {} of the if statement, where is says echo ‘Launch Website’. Paste your anchor link code into the single quotes after the echo and it should work.
Great tutorial! This is exactly what I was looking for. I’ve followed it but I’m getting a weird error in my dashboard that says: “Warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, ‘admin_portfolio’ was given in /…/wp-includes/plugin.php on line 405″
I’m trying to figure out how to solve it and I think it has to do with the admin_init function but I’m not much of a developer so I can’t seem to figure out what it needs. Also, when I go to add an entry I’m missing the URL field etc. Could this be because I had previously used the same function name? Any advice would be appreciated and thanks for your hard work, I’m sure you’re tired of answering support questions by now.
@Ingrid – the “admin_portfolio” is the name of the function that is used to display the meta box. Make sure that if you changed the function name elsewhere, you change it everywhere. There should be two places the function name is used.
is this applicable in wordpress 3.2.1 version?
thank you.
@soulmenji – Yes. There are a few areas that could be updated a bit, but overall everything still works perfectly fine.
@pippin: thank you so much! i will try this one.
I will wait for more updates to this tutorial.
by the way i subscribed to this tutorial but i haven’t received any notification if someone replied to this thread any remedy?
@soulmenj – check your spam folder
@pippin: thank you … now its working
@pippin: do i need to copy the first set of codes and paste it in my function.php file and the rest of the code?
‘coz i ended with white page after saving the first snip of codes. “register_post_type();”
@soulmenj – All of the code needs to be pasted. I’ll help you get the issue worked on via email.
Please help, I cannot save my custom field… may I post the code here?
@Alessio – yes, you can post it here.
is there any update for this tutorials?
No, not at this time. Sorry.
no worries
thanks
Hello, Pippins i think you miss the end of while and if statement of no 7