WordpressCategory: Wordpress

WordPress Custom Post Types Customization : Create a Portfolio

I would like to start off by saying how ridiculously cool WordPress is and how I use it every time to develop websites. One of the best features in WordPress is the ability to create custom post types and using these custom post types to create creative features within WordPress website. This blog post will show you how to create a portfolio custom post type and learn how to use custom post types efficiently in your next web project. So let’s get started…

What are custom post types?

Don’t be confused by the term “post” in the name. It is actually an extremely generic term and should not be considered the same thing as a blog post. If you prefer, you can replace it with “content” instead.

Custom post types don’t have any strict rules that define what they are. They can represent any type of content you want. For example, WordPress ships with several default post types.

  • Blog Posts
  • Pages
  • Attachments
  • Revisions
  • Nav Menus (WordPress 3.0)

You should think of them as a way to create, edit, and store information in the same way as blog posts but with much more creative control.

One thing I would warn against is trying to separate your blog posts in this way. You have categories, tags, and custom taxonomies at your disposal if you’re just looking for a way to label them.

Creating custom post types

WordPress 2.9 introduced the register_post_type() function. It didn’t do a lot at the time, but WordPress 3.0 will make this a powerful tool.

To get the basic functionality of a custom post type working, we hardly have any code to input. Before you start, you at least need a few things: a name, two labels, and whether your post type will be public (you’ll likely want this).

You can either create a plugin file or use your theme’s functions.php file to add the code. I will assume at this point of the tutorial that you know how to work with at least one of those two things.

Let’s set up our Portfolio post type.

add_action('init', 'portfolio_register'); 
function portfolio_register() {
  register_post_type( 'my_portfolio',
    array(
	 'labels' => array(
	 'name' => _x('My Portfolio', 'post type general name'), 
         'singular_name' => _x('Portfolio Item', 'post type singular name'),
    ),
    'public' => true,
  ));
}

You’ll notice that there is not a lot going on there. We added two parameters: a post type name and an array of arguments. All of the possible arguments are detailed in the next section.

If all you’ll ever want to do is something as basic as having a title field and content textarea, you can skip over the next portion of this tutorial. But if you want to create a really customized solution then read below where I will break down the parameters within the register_post_type()

labels

The labels argument is an array of strings that represents your post type in the admin. Each string is a bit of text shown for particular function in the admin. By default, non-hierarchical post types will have text with “post” in them and hierarchical post types will have text with “page” in them.

It is particularly important that you make these strings translatable if you’re creating a plugin for public use.

This list is a set of general examples of when each string is used. However, each may be used in multiple places in the admin.

  • name: The plural form of the name of your post type.
  • singular_name: The singular form of the name of your post type.
  • add_new: The menu item for adding a new post.
  • add_new_item: The header shown when creating a new post.
  • edit: The menu item for editing posts.
  • edit_item: The header shown when editing a post.
  • new_item: Shown in the favorites menu in the admin header.
  • view: Used as text in a link to view the post.
  • view_item: Shown alongside the permalink on the edit post screen.
  • search_items: Button text for the search box on the edit posts screen.
  • not_found: Text to display when no posts are found through search in the admin.
  • not_found_in_trash: Text to display when no posts are in the trash.
  • parent: Used as a label for a parent post on the edit posts screen. Only useful for hierarchical post types.
'labels' => array(
	'name' => __( 'Portfolio' ),
	'singular_name' => __( 'Portfolio' ),
	'add_new' => __( 'Add New' ),
	'add_new_item' => __( 'Add New Portfolio Item' ),
	'edit' => __( 'Edit' ),
	'edit_item' => __( 'Edit Portfolio Item' ),
	'new_item' => __( 'New Portfolio Item' ),
	'view' => __( 'View Portfolio' ),
	'view_item' => __( 'View Portfolio Item' ),
	'search_items' => __( 'Search Portfolio Items' ),
	'not_found' => __( 'No Portfolio Items found' ),
	'not_found_in_trash' => __( 'No Portfolio Items found in Trash' ),
	'parent' => __( 'Parent Portfolio' ),
),

public

The public argument is a kind of catchall argument for several other arguments and defaults to false. Depending on whether it’s set to true or false, it’ll automatically decide what other arguments should be unless they’re specifically defined. If you’re looking for finer control over the public arguments, there are three specific arguments you may set:

  • show_ui: Whether to show the administration screens.
  • publicly_queryable: Whether queries for this post type can be performed from the front end.
  • exclude_from_search: Whether the posts should appear in search results.
'public' => true,
'show_ui' => true,
'publicly_queryable' => true,
'exclude_from_search' => false,

menu_position

By default, a new post type is added after the Comments menu item in the admin. But, you have to ability to move it to a position more suitable for you. Default WordPress menu items are set apart by integrals of 5. For example, using 20 will add your menu item after Pages.

'menu_position' => 20,

menu_icon

New post types will default to the Posts menu icon, but if you want to mix it up a bit or give your post type some separation from other elements, you can define a custom icon. You only have to input a a custom URL to an image file.

'menu_icon' => get_stylesheet_directory_uri() . '/images/article16.png',

hierarchical

The hierarchical argument allows you to choose whether you want your post type to be hierarchical. It defaults to false. If you set it to true, your posts will behave like pages in WordPress.

'hierarchical' => true,

query_var

The query_var argument allows you to control the query variable used to get posts of this type. For example, you could use it with the query_posts() function or WP_Query class. This will default to the name of your taxonomy.

'query_var' => true,

capability_type / capabilities

The capability_type argument is another catchall argument for several more specific arguments and defaults to post. It allows you to define a custom set of capabilities, which are permissions to edit, create, and read your custom post type.

If you just want to keep the same permissions you have with blog posts, leave this at the default. Otherwise, you can either set capability_type to something custom or define each specific capability in the capabilities array.

  • edit_post: Whether someone can create and edit a specific post of this post type.
  • edit_posts: Capability that allows editing posts of this post type.
  • edit_others_posts: Capability that allows editing of others posts.
  • publish_posts: Capability to grant publishing of these types of posts.
  • read_post: Capability that controls reading of a specific post of this post type.
  • read_private_posts: Capability to allow reading of private posts.
  • delete_post: Capability that grants the privilege of deleting posts.

For most people that need control over these things, it’s easier to just change capability_type to something like portfolio. WordPress will automatically switch the other caps to follow this pattern. For example, the edit_post capability would become edit_portfolio. Of course, capability control means nothing without being able to choose who has the capabilities. So here is an example of some custom capabilities for our portfolio:

/* Global control over capabilities. */
'capability_type' => 'portfolio',
 
/* Specific control over capabilities. */
'capabilities' => array(
	'edit_post' => 'edit_portfolio',
	'edit_posts' => 'edit_portfolios',
	'edit_others_posts' => 'edit_others_portfolios',
	'publish_posts' => 'publish_portfolios',
	'read_post' => 'read_portfolio',
	'read_private_posts' => 'read_private_portfolios',
	'delete_post' => 'delete_portfolio',
),

supports

The supports argument allows you to define what meta boxes and other fields will appear on the screen when editing or creating a new post. This defaults to title and editor. There are several available options:

  • title: Text input field to create a post title.
  • editor: Content input box for writing.
  • comments: Ability to turn comments on/off.
  • trackbacks: Ability to turn trackbacks and pingbacks on/off.
  • revisions: Allows revisions to be made of your post.
  • author: Displays a select box for changing the post author.
  • excerpt: A textarea for writing a custom excerpt.
  • thumbnail: The thumbnail (featured image in 3.0) uploading box.
  • custom-fields: Custom fields input area.
  • page-attributes: The attributes box shown for pages. This is important for hierarchical post types, so you can select the parent post.
'supports' => array( 'title', 'editor', 'excerpt', 'custom-fields', 'thumbnail' ),

rewrite

The rewrite argument allows you to define the permalink structure of your posts when viewing the single post. For example, you may want to have a structure like yoursite.com/portfolio/post-name. WordPress will set up a default structure based on your taxonomy name. The rewrite argument can be set to true, false, or an array of values. It takes two arguments:

  • slug: The slug you’d like to prefix your posts with.
  • with_front: Whether your post type should use the front base from your permalink settings (for example, if you prefixed your structure with /blog or /archives).
'rewrite' => array( 'slug' => 'portfolio', 'with_front' => false ),

taxonomies

If you have some preexisting taxonomies, you can allow posts of this type to also use those taxonomies. You just have to set an array of taxonomy names that you’d like for it to use. WordPress will handle all the administration features for you. There is more to taxonomies but that will be another blog post in the future.

'taxonomies' => array( 'post_tag', 'category '),

can_export

You can use the can_export argument to decide whether posts of your post type can be exportable via the WordPress export tool. By default, this is set to true.

'can_export' => true,

register_meta_box_cb

This feature will likely only be useful to developers. You can create a custom callback function that is called when the meta boxes for the post form are set up.

'register_meta_box_cb' => 'your_callback_function_name',

Putting It All Together

Now that you know about all the parameters and their meanings lets put some code together to create the portfolio and the fields required to add the images and build the portfolio items:

<?php
add_action('init', 'portfolio_register');
function portfolio_register() {
 
	$labels = array(
		'name' => _x('My Portfolio', 'post type general name'),
		'singular_name' => _x('Portfolio Item', 'post type singular name'),
		'add_new' => _x('Add New', 'portfolio item'),
		'add_new_item' => __('Add New Portfolio Item'),
		'edit_item' => __('Edit Portfolio Item'),
		'new_item' => __('New Portfolio Item'),
		'view_item' => __('View Portfolio Item'),
		'search_items' => __('Search Portfolio'),
		'not_found' =>  __('Nothing found'),
		'not_found_in_trash' => __('Nothing found in Trash')
	);
 
	$args = array(
		'labels' => $labels,
		'public' => true,
		'publicly_queryable' => true,
		'show_ui' => true,
		'query_var' => true,
		'menu_icon' => get_stylesheet_directory_uri() . '/images/article16.png',
		'rewrite' => true,
		'capability_type' => 'post',
		'hierarchical' => false,
		'menu_position' => null,
		'supports' => array('title','editor','thumbnail')
	  ); 
 
	register_post_type( 'myportfolio' , $args );
    flush_rewrite_rules();
}
register_taxonomy("myservices", array("myportfolio"), array("hierarchical" => true, "label" => "Services", "singular_label" => "Service", "rewrite" => true));
 
add_action("admin_init", "admin_init");
function admin_init(){
  add_meta_box("web_url-meta", "Website URL", "web_url", "myportfolio", "normal", "low");
}
function web_url(){
  global $post;
  $meta = get_post_meta($post->ID, 'web_url', true);
  ?>
  <p><input style="width:350px;" name="web_url" value="<?php echo $meta; ?>" /></p>
  <?php
}
 
add_action('save_post', 'save_details');
function save_details($post_id){
  global $post;
  if(isset($_POST['post_type']) && ($_POST['post_type'] == "myportfolio")) {
   $data = $_POST['web_url'];
   update_post_meta($post_id, 'web_url', $data);
  }
}
 
 
add_action("manage_posts_custom_column",  "myportfolio_custom_columns");
add_filter("manage_edit-myportfolio_columns", "myportfolio_edit_columns");
function myportfolio_edit_columns($columns){
  $columns = array(
    "cb" => "<input type=\"checkbox\" />",
    "title" => "Project Title",
    "description" => "Description",
    "web_url" => "Web URL",
    "myservices" => "Services",
  );
 
  return $columns;
}
function myportfolio_custom_columns($column){
  global $post;
 
  switch ($column) {
    case "description":
      the_excerpt();
      break;
    case "web_url":
      $custom = get_post_custom();
      echo $custom["web_url"][0];
      break;
    case "myservices":
      echo get_the_term_list($post->ID, 'myservices', '', ', ','');
      break;
  }
}
?>
ShortURL: http://goo.gl/tYs95

This entry was posted by Rusty on at and is filed under Wordpress. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Next/Prev Posts:



Leave a Reply

You must be logged in to post a comment.