Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Custom WordPress theme development


Published on

Go over a quick crash course into what it takes to develop a WordPress theme and then jump into some deeper waters on how to utilize Custom Post Types, create custom theme options, and custom meta boxes.

Published in: Education, Technology

Custom WordPress theme development

  1. 1. Custom WORDPRESS THEMEDevelopment<br />Tech Mixer University 2011<br />
  2. 2. Intro to Theme Development<br />Crash course<br />
  3. 3. What is a WordPress theme?<br />A group of templates and a stylesheet that displays content entered into the database via the WordPress admin.<br />At a minimum, you need:<br />index.php<br />style.css<br />
  4. 4. Index.php<br /><html><br /><head><br /><link rel="stylesheet" href="<?bloginfo('stylesheet_url');?>" type="text/css" media="screen" /><br /><title><?wp_title('');?></title><br /></head><br /><body><br /> <header><?bloginfo('name');?></header><br /><nav><?wp_list_pages(); ?></nav><br /><section><br /> …loop with <article />…<br /></section><br /><footer>© <?=date('Y').' '.get_bloginfo('name');?></footer><br /></body><br /></html><br />
  5. 5. Style.css<br />/* <br />Theme Name: Twenty Ten <br />Theme URI: <br />Description: The 2010 default theme for WordPress. <br />Author: wordpressdotorg <br />Author URI: <br />Version: 1.0 <br />Tags: black, blue, white, two-columns, fixed-width, custom-header, custom-background, threaded-comments, sticky-post, translation-ready, microformats, rtl-language-support, editor-style, custom-menu (optional) <br />License: <br />License URI: <br />General comments (optional). <br />*/<br />
  6. 6. What is the Loop?<br />PHP that uses the prefetched query of the current page to loop through the posts and displays the data as outlined in the current page’s template.<br />
  7. 7. Basic Loop<br /><? if (have_posts()) : while(have_posts()) : the_post(); ?><br /><h2><a href="<?the_permalink(); ?>"><?the_title(); ?></a></h2><br /><?the_content(); ?><br /><p class="postmetadata"><br /><?the_date('F j, Y');?><br />Posted in: <?the_category(', ');?><br /></p><br /><?endwhile; else: ?><br /><p>No Posts Found</p><br /><?endif;?><br />
  8. 8. Custom Loop<br /><? <br />$args =array(<br />'post_type'=> 'movie',<br />'numberposts'=>10,<br />'meta_key'=>'production_year',<br />'meta_value'=>'1983',<br />'orderby' =>'meta_value'<br />);<br />$loop =newWP_query($args);<br />if ($loop->have_posts()) : while($loop->have_posts()) : $loop->the_post(); ?><br />… stuff …<br /><?endwhile; else: ?><br /><p>No Posts Found</p><br /><?endif;?><br />
  9. 9. Template Hierarchy<br />Different kinds of WordPress magic happens on templates depending on what the template name is.<br />
  10. 10. Common Pages<br />Archive Pages<br />Homepage<br />home.php<br />index.php<br />Single Post display<br />single-{post_type}.php<br />single.php<br />index.php<br />Page display<br />custom template<br />page-{slug}.php<br />page-{id}.php<br />page.php<br />index.php<br />Search Result display<br />search.php<br />index.php<br />404 (Not Found) display<br />404.php<br />index.php<br />Attachment display<br />MIME_type.php<br />attachment.php<br />single.php<br />index.php<br />Category display<br />category-{slug}.php<br />category-{id}.php<br />category.php<br />archive.php<br />index.php<br />Tag display<br />tag-{slug}.php<br />tag-{id}.php<br />tag.php<br />archive.php<br />index.php<br />Custom Taxonomies<br />taxonomy-{taxonomy}-{term}.php <br />taxonomy-{taxonomy}.php<br />taxonomy.php<br />archive.php<br />index.php<br />Custom Post Types display<br />archive-{post_type}.php <br />archive.php<br />index.php<br />Author display<br />author-{nicename}.php<br />author-{id}.php<br />author.php<br />archive.php<br />index.php<br />Date display<br />date.php<br />archive.php<br />index.php<br />
  11. 11. Template Hierarchy<br />It all ends at the index<br />
  12. 12. A Basic Theme<br />404.php - Custom “not found” page<br />archive.php - Overall template for archived content<br />attachment.php- Overall template for attachments of any mime type<br />comments.php - The template called with comments_template()<br />footer.php - The template called with get_footer()<br />functions.php - A place to create custom functions, register sidebars, and other settings<br />header.php - The template called with get_header()<br />index.php - The basic home template<br />page.php - Overall template for pages<br />search.php - Search results template<br />searchform.php - The template called with get_search_form()<br />sidebar.php - The template called with get_sidebar()<br />single.php - Overall template for single posts<br />style.css - The main stylesheet<br />
  13. 13. Bonus Template Functions<br />Call alternate comment, sidebar, header, and footer templates<br />short-comments.php - comments_template('/short-comments.php')<br />sidebar-simple.php - get_sidebar('simple');<br />header-simple.php - get_header('simple');<br />footer-simple.php - get_footer('simple');<br />
  14. 14. CustomPost Types & Taxonomies<br />Make your own stuff<br />
  15. 15. What is a Post Type?<br />Content entered into the database goes into the posts tableand is assigned a post_type.<br />
  16. 16. Default Post Types<br />Main Content<br />Post - blog style content<br />Page - static content<br />Other<br />Attachment - any images or other files uploaded to a post (of any type)<br />Revision - an archive of version of a particular post<br />Nav Menu Item - used in the menu system<br />
  17. 17. What is a Taxonomy?<br />Content can be organized by assigning terms to them. Terms are saved in the terms table, then they are grouped into a taxonomy in the term_taxonomy table, and finally they are related to posts in the term_relationships table.<br />
  18. 18. Default Taxonomies<br />Post Taxonomies<br />Category - hierarchical<br />Post Tag - non-hierarchical<br />Other<br />Link Category - for the links system<br />Nav menu - used in the menu system<br />
  19. 19. Custom Examples<br />Post Type: Movie<br />Taxonomy: Actor<br />Term: Debbie Reynolds<br />Term: Angeline Jolie<br />Term: Clark Gable<br />Term: Ewan McGregor<br />Taxonomy: Director<br />Term: Ron Howard<br />Term: Steven Spielberg<br />Post Type: Book<br />Taxonomy: Author<br />Term: Frank Peretti<br />Term: James Patterson<br />Term: Seth Godin<br />Term: Lynn Austin<br />Taxonomy: Publisher<br />Term: Atlas Press<br />Term: Hay House<br />Term: O’Reilly Media<br />Taxonomy: Subject<br />Term: Arts & Photography<br />Term: Suspense & Horror<br />Term: Reference<br />Post Type: Photo<br />Taxonomy: Album<br />Term: Summer<br />Child Term: Fourth of July<br />Child Term: First Day of School<br />Term: Christmas<br />Term: Sports<br />Taxonomy: Year<br />Term: 2001<br />Term: 2002<br />Term: 2003<br />Post Type: Project<br />Taxonomy: Type<br />Term: Design<br />Child Term: Logo<br />Child Term: Brochure<br />Child Term: Website<br />Term: Development<br />Taxonomy: Tools<br />Term: Photoshop<br />Term: HTML5<br />Term: JavaScript<br />Term: WordPress<br />
  20. 20. Useful Plugins<br />Like most things in WordPress, there are plugins that help create and manage Custom Post Types and Taxonomies.<br />
  21. 21. Create<br />Manage<br />Custom Post Type UI<br />Creates Both<br />TONS of labeling options<br />WP Post Type UI<br />Creates Both<br />Buggy<br />Allows a custom icon<br />More Types & More Taxonomies<br />Separate plugins for each<br />Allows you to override built in types and taxonomies<br />Allows a custom icon<br />Works seamlessly with the More Fields Plugin (stay tuned for more)<br />Custom Post Type Order<br />Drag and drop ordering<br />Post Type Switcher<br />Change the post type one item at a time<br />Convert Post Types<br />Bulk edit post types<br />Term Management Tools<br />Merge - combine two or more terms into one<br />Set parent - set the parent for one or more terms (for hierarchical taxonomies)<br />Change taxonomy - convert terms from one taxonomy to another <br />
  22. 22. Registration Code<br />The best method for creating Custom Post Types and taxonomies for is to register them yourself without a plugin.<br />
  23. 23. register_post_type()<br />add_action( 'init', 'register_cpt_project');<br />functionregister_cpt_project() {<br />$labels = array(<br />'name‘ => _x('Projects','project'),<br />'singular_name' => _x('Project','project' ),<br />'add_new‘ => _x( 'Add New','project' ),<br />'add_new_item' => _x('Add New Project','project'),<br />'edit_item' => _x( 'Edit Project','project' ),<br />'new_item' => _x('New Project', 'project'),<br />'view_item' => _x( 'View Project','project'),<br />'search_items‘ => _x('Search Projects', 'project'),<br />'not_found' => _x('No projects found', 'project'),<br />'not_found_in_trash' => _x('No projects found in Trash','project'),<br />'parent_item_colon' => _x('Parent Project:','project'),<br />'menu_name' => _x('Projects ','project')<br />);<br />$args = array(<br /> 'labels' =>$labels,<br /> 'hierarchical' =>false, <br /> 'supports‘ =>array('title','editor','thumbnail' ), <br /> 'public' =>true,<br /> 'show_ui' =>true,<br /> 'show_in_menu' =>true,<br />'show_in_nav_menus' =>false,<br /> 'publicly_queryable' =>true,<br /> 'exclude_from_search' =>false,<br /> 'has_archive' =>true,<br /> 'query_var' =>true,<br /> 'can_export' =>true,<br /> 'rewrite' =>true,<br /> 'capability_type' =>'post'<br />);<br />register_post_type('project',$args );<br />}<br />
  24. 24. register_taxonomy()<br />add_action( 'init', 'register_taxonomy_type');<br />functionregister_taxonomy_type() {<br />$labels = array( <br />'name' => _x( 'Types', 'type'),<br />'singular_name' => _x( 'Type', 'type'),<br />'search_items‘ => _x( 'Search Types', 'type' ),<br />'popular_items' => _x( 'Popular Types', 'type'),<br />'all_items‘ => _x( 'All Types', 'type'),<br />'parent_item' => _x( 'Parent Type', 'type'),<br />'parent_item_colon' => _x( 'Parent Type:', 'type'),<br />'edit_item' => _x( 'Edit Type', 'type'),<br />'update_item' => _x( 'Update Type', 'type'),<br />'add_new_item' => _x( 'Add New Type', 'type'),<br />'new_item_name' => _x( 'New Type Name', 'type'),<br />'add_or_remove_items' => _x( 'Add or remove types', 'type'),<br />'menu_name' => _x( 'Types', 'type'),<br />);<br />$args = array( <br />'labels' => $labels,<br />'public‘ => true,<br />'show_in_nav_menus' => true,<br />'show_ui' => true,<br />'show_tagcloud' => false,<br />'hierarchical‘ => true,<br />'rewrite' => true,<br />'query_var' => true<br />);<br />register_taxonomy( 'type', 'project', $args );<br />}<br />
  25. 25. There’s still an easy way out<br />Don’t get too worried about memorizing all of this. Just memorize the web address where you can find two amazing generators:<br /><br />
  26. 26. CustomMeta Boxes<br />Need more input<br />
  27. 27. What are Custom Fields?<br />The postmeta table holds extra data and options attached to each post. Custom fields can be used by theme and plugin developers to save extra pieces of information that you can use in templates and other places.<br />
  28. 28. How Custom fields work<br />The data is saved in the postmeta table<br />meta_id - the ID of the item being saved<br />post_id - the ID of the post it belongs to<br />meta_key - the name of the data being collected<br />meta_value - the entered value<br />Use the data in a template or function<br />get_post_meta() - returns the values of the specified key<br />the_meta() - outputs a simple list of all custom fields and their values<br />get_post_custom()- returns a multidimensional array with all custom fields of a particular post or page<br />
  29. 29. Code Examples<br />Example 1:<br />$my_key = get_post_meta($post->ID, 'my_key', true);<br />if ($my_key != '')<br />echo'<p>' . $my_key . '</p>';<br />Example 2:<br /><? $my_meta = get_post_custom(); ?><br /><ul class="my_meta"><br /> <li><b>Nice Label 1:</b> <?=$meta['my_key_1'][0]; ?></li><br /> <li><b>Nice Label 2:</b> <?=$meta['my_key_2'][0]; ?></li><br /> <li><b>Nice Label 3:</b> <?=$meta['my_key_3'][0]; ?></li><br /></ul><br />
  30. 30. Custom Fields<br />Edit post screen<br />
  31. 31. Create Your Own UI<br />Adding a meta box for entering in values for custom fields can make it so much easier for the user to add things like dates or select from a premade list of values.<br />
  32. 32. add_meta_box()<br />add_meta_box( $id, $title, $callback, $page, $context, $priority, $callback_args );<br />$id - HTML 'id' attribute of the edit screen section<br />$ title - title of the edit screen section, visible to user<br />$callback - function that prints out the HTML for the edit screen section.<br />$page - the type of Write screen on which to show the edit screen section<br />$context - the part of the page where the edit screen section should be shown<br />$priority - the priority within the context where the boxes should show<br />$callback_args- arguments to pass into your callback function<br />add_action('admin_menu', 'project_add_box');<br />function project_add_box() {<br />global$meta_fields;<br /> add_meta_box('project_info', 'Project Info', 'project_show_box', 'project', 'normal', 'high');<br />}<br />
  33. 33. Array of Fields<br />$meta_fields =array(<br /> array(<br /> 'name' => 'Project URL',<br /> 'desc' =>'URL to the live site.',<br /> 'id' => 'url',<br /> 'type' =>'text',<br /> 'value' => 'http://'<br />),<br /> array(<br /> 'name' => 'Project Date',<br /> 'desc' =>'When the project was released.',<br /> 'id' =>'date',<br />'type‘ => 'date'<br />),<br /> array(<br /> 'name' => 'Tools',<br /> 'desc' =>'What tools did you use for this project?',<br /> 'id' =>'tools',<br /> 'type' =>'checkbox_group',<br /> 'options' =>array( 'jQuery', 'HTML5', 'CSS 3', 'Photoshop', 'Illustrator', 'WordPress')<br /> )<br />);<br />
  34. 34. Callback<br />function project_show_box() {<br /> global$meta_fields, $post;<br /> // Use nonce for verification<br /> echo'<input type="hidden" name="project_meta_box_nonce" value="', wp_create_nonce(basename(__FILE__)), '" />';<br />// start a table<br /> echo'<table class="form-table">';<br />// start a loop through the fields<br /> foreach ($meta_fields as $field) { <br />// get current post meta data<br />$meta = get_post_meta($post->ID, $field['id'], true);<br />// start a table row<br />echo'<tr> <th style="width:20%"><label for="', $field['id'], '">', $field['name'], '</label></th>',<br />'<td>';<br />
  35. 35. Switch Case<br /> switch($field['type']) {<br />// text<br />case'text':<br />echo'<input type="text" name="', $field['id'], '" id="', $field['id'], '" value="', $meta ? $meta : $field['value'], '" size="30" style="width:97%" /> <br /><span class="desc">', $field['desc'], '</span>';<br />break;<br /> … continue with other field types …<br />} // end switch<br />echo'<td>', '</tr>';<br /> } // end foreach<br />echo'</table>';<br />}<br />
  36. 36. Save Post<br />add_action('save_post', 'project_save_data');<br />// Save data from meta box<br />function project_save_data($post_id) {<br />global$meta_fields;<br />// verify nonce<br />if(!wp_verify_nonce($_POST['project_meta_box_nonce'], basename(__FILE__))) <br />return$post_id;<br />// check autosave<br />if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)<br />return$post_id;<br />// check permissions<br />if ('page' == $_POST['post_type']) {<br />if (!current_user_can('edit_page', $post_id))<br /> return $post_id;<br /> } elseif (!current_user_can('edit_post', $post_id)) {<br />return$post_id;<br /> }<br />foreach($meta_fieldsas$field) {<br />// get the current value<br />$old = get_post_meta($post_id, $field['id'], true);<br />// get the new value<br />$new = $_POST[$field['id']];<br />// update if there’s a new value<br />if($new && $new != $old) {<br /> update_post_meta($post_id, $field['id'], $new);<br />// delete if the new value is empty<br /> } elseif ('' == $new && $old) {<br /> delete_post_meta($post_id, $field['id'], $old);<br /> }<br /> }<br />}<br />
  37. 37. Custom Meta Box UI<br />
  38. 38. Output the Data<br />Using the functions we discussed before, we can now use this data in our template.<br />
  39. 39. The Bad and the Ugly<br />The Bad:<br />$url = get_post_meta($post->ID, ‘url', true);<br />if ($my_key != '')<br />echo'<a href="' . $my_key . '“>Visit Site &rarr;</p>';<br />The Ugly:<br />the_meta();<br />
  40. 40. The Good<br /><? <br />$meta = get_post_custom();<br />// url<br />$url = $meta['url'][0];<br />// date<br />$date = $meta['date'][0];<br />$date = strtotime($date);<br />$date = date('F j, Y', $date);<br />// tools<br />$tools = $meta['tools'][0];<br />$tools = unserialize($tools);<br />$tools = implode(', ', $tools);<br />?><br /><ul class="post-meta"><br /><li><a href="<?=$url;?>">Visit Site &rarr;</a></li><br /><li><b>Release Date:</b> <?=$date;?></li><br /><li><b>Tools Used:</b> <?=$tools;?></li><br /></ul><br />
  41. 41. CustomTheme Options<br />Even more stuff<br />
  42. 42. Why is this useful?<br />You can create an easy way to input additional data that can be used in a variety of ways in your theme.<br />
  43. 43. Example Usages<br />Social Networks<br />The user can insert their twitter, facebook, etc. handles once<br />The template outputs these in the necessary places of the theme<br />On/Off switches<br />Show secondary navigation?<br />Are you available for live chat?<br />Use Breadcrumbs?<br />Custom layout options<br />Two column featured posts<br />3 Category Posts<br />Featured slider with recent posts listed below<br />
  44. 44. Create Your Own<br />This is almost as simple as adding a custom meta box, except the data isn’t limited to just a post, it can be used site wide.<br />
  45. 45. add_theme_page()<br />add_theme_page( $page_title, $menu_title, $capability, $menu_slug, $function);<br />$page_title - the text to be displayed in the title tags of the page when the menu is selected<br />$menu_title - the text to be used for the menu<br />$capability - the capability required for this menu to be displayed to the user<br />$menu_slug - the slug name to refer to this menu by (should be unique for this menu)<br />$function - the function to be called to output the content for this page<br />add_action( 'admin_menu', 'theme_options_add_page');<br />functiontheme_options_add_page() {<br />add_theme_page( 'Theme Options','Theme Options','edit_others_posts','theme_options', 'theme_options_do_page');<br />}<br />
  46. 46. register_setting()<br />register_setting( $option_group, $option_name, $sanitize_callback );<br />$option_group - settings group name<br />$option_name - the name of an option to sanitize and save <br />$sanitize_callback - a callback function that sanitizes the option's value<br />add_action( 'admin_init', 'theme_options_init' );<br />function theme_options_init(){ <br /> register_setting( 'our_options', 'our_theme_options', 'theme_options_validate');<br />}<br />
  47. 47. Array of Fields<br />$fields = array(<br />array(<br />'label' => 'Social Media',<br />'type' => 'section'<br /> ),<br />array(<br />'label' => 'Facebook',<br />'id' => 'facebook',<br />'type' => 'text',<br />'desc' => 'Facebook URL'<br /> ),<br />array(<br />'label' => 'Youtube',<br />'id' => 'youtube',<br />'type' => 'text',<br />'desc' => 'Youtube URL'<br />),<br />array(<br />'label' => 'Twitter',<br />'id' => 'twitter',<br />'type' => 'text',<br />'desc' => 'Twitter URL'<br /> ),<br />array(<br />'label' => 'Miscellaneous',<br />'type' => 'section'<br /> ),<br />array(<br />'label' => 'Featured Video',<br />'id' => 'featvideo',<br />'type' => 'text',<br />'desc' => 'Youtube URL for video to be featured on the homepage.'<br /> )<br />);<br />
  48. 48. Callback<br />function theme_options_do_page() {<br />global$fields;<br />if(!isset( $_REQUEST['settings-updated']))<br />$_REQUEST['settings-updated'] = false;<br />// the page heading<br />echo'<div class="wrap">';<br />screen_icon();<br />echo'<h2>Theme Options</h2>';<br />// notifies on load if options were saved<br />if(false!== $_REQUEST['settings-updated'])<br />echo'<div class="updated fade"><p><strong>Options saved</strong></p></div>';<br />// start form<br />echo'<form method="post" action="options.php">';<br /> settings_fields( 'our_options' );<br />// get the settings<br />$options = get_option('our_theme_options');<br />// start a table<br />echo'<table id="options" class="form-table">';<br />// start a loop through the fields<br />foreach($fields as$field) {<br />// section rows<br />if($field['type'] == 'section') {<br />echo'<tr><td colspan="2"><h3>', $field['label'], '</h3></td></tr>';<br />}<br />// field rows<br />else{<br />// start a table row<br />echo'<tr valign="top"><th scope="row">', $field['label'], '</th>',<br />'<td>';<br />
  49. 49. Switch Case<br /> switch ($field['type']) {<br />// text<br />case'text':<br />echo'<input type="text" name="our_the_options[', $field['id'], ']" id="', $field['id'], '" value="', $meta ? $meta : $field['value'], '" size="30" style="width:97%" /> <br /><span class="desc">', $field['desc'], '</span>';<br />break;<br /> … continue with other field types …<br />} // end switch<br />echo'<td>', '</tr>';<br /> } // end foreach<br />echo'</table>';<br />// close out the container<br />echo'<p class="submit"><input type="submit" class="button-primary" value="Save Options" /></p></form></div>';<br />}<br />
  50. 50. Save Data<br />function theme_options_validate( $input ) {<br />global$fields;<br />foreach ($fieldsas$field) {<br />switch ($field['type']) {<br />//text<br />case'text':<br />// Say our text option must be safe text with no HTML tags<br />$input[$field['id']] = wp_filter_nohtml_kses( $input[$field['id']] );<br />break;<br /> … continue with other field types …<br />} // end switch<br /> } // end foreach<br />return$input;<br />}<br />
  51. 51. Theme Options<br />Our custom fields<br />
  52. 52. Output the Data<br />Create a function to call the data from the setting and use it in your templates.<br />
  53. 53. Custom Functions<br />// get the value we saved<br />function get_our_options($field) {<br />$options = get_option('our_theme_options');<br />return$options[$field];<br />}<br />// print the value<br />function our_options($field) {<br />print get_our_options($field);<br />}<br />
  54. 54. Output<br />Social Links:<br /><ul class="social-links"><br /> <li><a href="<?our_options('facebook');?>">Facebook</a></li><br /> <li><a href="<?our_options('youtube');?>">Youtube</a></li><br /> <li><a href="<?our_options('twitter');?>">Twitter</a></li><br /></ul><br />Miscellaneous:<br /><div class="featured-video"><br /><?=apply_filters('the_content',get_our_options('featvideo'));?><br /></div><br />
  55. 55. Download<br />See these slides and get all of the code we covered today:<br /> <br />
  56. 56. Thank You! Questions?<br />Tammy Hart<br />@tammyhart<br /><br /><br />