WordPress Custom Post Types Unveiled
In this tutorial, we will illustrate how to create a WordPress custom post type called My Things. I have narrowed the procedure down to 4 steps, which will be explained in depth. The most obvious place to insert the code is somewhere within your functions.php, but to add another level of organization, I recommend linking to a separate file. In my first attempts at creating WordPress custom post types, I reviewed numerous articles explaining how. Some are better than others, and a few were exceptionally helpful, yet none were the whole enchilada. So here is my attempt to document & share exactly what worked for me.
Outline
Below is a oversimplified outline of a wordpress custom post type. It is not meant for cutting & pasting, but rather to help familiarize you with the fundamental steps for preparing your custom post type. Also, it is good practice to prefix your IDs in order to make them more unique. In this case, we will be using mt_, as in My Things.
// Part I: Initialize & Register
add_action( 'init', 'mythings_init' );
function mythings_init() {
register_post_type(
'mythings', // $post_type -- your post type slug
/* YOUR POST TYPE ARGUMENTS */
);
}
// Part II: Add Taxonomies
add_action( 'init', 'create_mythings_taxonomies' );
function create_mythings_taxonomies() {
register_taxonomy(
'mt_groups', // $taxonomy
'mythings', // $object_type -- stick with $post_type for now
/* YOUR TAXONOMY ARGUMENTS */
);
}
// Part III: Add Metaboxes
add_action( 'admin_init', 'mt_admin_init' );
function mt_admin_init(){
add_meta_box(
/* SETUP YOUR META BOX ARGUMENTS HERE */
);
function mt_first_metabox() {
/* CREATE YOUR ADMIN FORM */
}
// Part IV: Save your Data
add_action('save_post', 'mt_save_data');
function mt_save_data(){
/* YOUR FORM-SAVING CODE */
}
And that’s it in a nutshell. Now we can swap in some usable code.
Part I: Basic
This will start the job off right, but in its simplest form. WordPress secretly provides us with a number of handy default arguments, which saves us a lot of real estate in this example.
This example differs slightly from that of WordPress Codex. It has been recommended on new2wp.com to save the register( ) function until after the init( ) function. I believe I have felt the adverse side effects of doing it the other way around.
// create your init() function
add_action( 'init', 'mythings_init' );
// use your init() function
function mythings_init() {
array(
'labels' => array(
'name' => __( 'Things' ), // general name in menu & admin page
'singular_name' => __( 'Thing' )
),
'public' => true,
'has_archive' => true,
)
);
// now register the post type
register_post_type( 'mythings', $args );
}
Part I: Advanced
You will find yourself wanting to be much more specific, so this example includes most of the different parameters, and I’ve done my best to comment on their function. Since we have a lot more information to add, we will be as organized as possible by utilizing the custom variables $labels and $args.
// add your init() function
add_action( 'init', 'mythings_init' );
// use your init() function
function mythings_init() {
// setup an array called $labels to insert into 'labels'
$labels = array(
'name' => ( 'Things' ),
'singular_name' => ( 'Thing' ),
'add_new' => ( 'Add New', 'mythings' ),
'add_new_item' => ( 'Add New Thing' ),
'edit_item' => ( 'Edit Thing' ),
'new_item' => ( 'New Thing' ),
'view_item' => ( 'View Thing' ),
'search_items' => ( 'Search Things' ),
'not_found' => ( 'No thingamajigs found' ),
'not_found_in_trash' => ( 'No thingamajigs found in Trash' ),
'parent_item_colon' => ''
);
// setup an array called $args to insert into 'args'
$args = array( 'labels' => $labels, // adds your $labels array from above
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'query_var' => true,
'capability_type' => 'post',
'hierarchical' => false,
// choose name used within permalink structure
'rewrite' => array( 'slug' => 'things' ), // changes name in permalink structure
'menu_position' => null, // search WordPress Codex for menu_position parameters
'supports' => array(
'title',
'editor', // adds the default text editor
'author',
'thumbnail', // adds Featured Image metabox**
'comments'
)
);
// now register the post type
register_post_type( 'mythings', $args ); // adds your $args array from above
// flush the rewrite rules so you don't have to visit Settings > Permalinks
flush_rewrite_rules();
} // end of mythings_init() function
**NOTE: Including ‘thumbnail’ in the support parameters hasn’t always worked for me on it’s own. If it doesn’t, you can add this function after that last “}”
// enable Featured Image attachments
add_theme_support('post-thumbnails');
Mental Note: You can define & redefine $labels, or any of your custom variables, as often as you wish.
If all went well, Things should now appear in your admin menu, and you should be able to view All Things and Add New. If that checks out, you are ready for the next step.
Part II: Create Your Custom Taxonomies
Taxonomies are not required, but if you do want to add them, now is the time. You’ll see that we can use much of the same format from above.
// add action to create your custom taxonomies
add_action( 'init', 'create_mythings_taxonomies' );
// use your action
function create_mythings_taxonomies() {
// add a hierarchical taxonomy called Group (same as Post Categories)
// create the array for 'labels'
$labels = array(
'name' => ( 'Groups' ),
'singular_name' => ( 'Group' ),
'search_items' => ( 'Search Groups' ),
'all_items' => ( 'All Groups' ),
'parent_item' => ( 'Parent Group' ),
'parent_item_colon' => ( 'Parent Group:' ),
'edit_item' => ( 'Edit Group' ),
'update_item' => ( 'Update Group' ),
'add_new_item' => ( 'Add New Group' ),
'new_item_name' => ( 'New Group Name' ),
);
// register your Groups taxonomy
register_taxonomy( 'mt_groups', array( 'mythings' ), array(
'hierarchical' => true,
'labels' => $labels, // adds the above $labels array
'show_ui' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'mygroups' ), // changes name in permalink structure
));
// add a non-hierarchical taxonomy called Flags (same as Post Tags)
// create the array for 'labels'
$labels = array(
'name' => ( 'Flags' ),
'singular_name' => ( 'Flag' ),
'search_items' => ( 'Search Flags' ),
'popular_items' => ( 'Popular Flags' ),
'all_items' => ( 'All Flags' ),
'parent_item' => null,
'parent_item_colon' => null,
'edit_item' => ( 'Edit Flag' ),
'update_item' => ( 'Update Flag' ),
'add_new_item' => ( 'Add New Flag' ),
'new_item_name' => ( 'New Flag Name' ),
'separate_items_with_commas' => ( 'Separate Flags with commas' ),
'add_or_remove_items' => ( 'Add or remove Flags' ),
'choose_from_most_used' => ( 'Choose from the most used Flags' )
);
// register your Flags taxonomy
register_taxonomy( 'mt_flags', 'mythings', array(
'hierarchical' => false,
'labels' => $labels, // adds the above $labels array
'show_ui' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'myflags' ), // changes name in permalink structure
));
} // end of create_mythings_taxonomies() function
Now your two custom taxonomies should show up in your My Things dropdown menu.
Part III: Create Your Meta Boxes
This is important if you want your custom post type to do something more than Posts & Pages, and I hope you do…
// add function to put metaboxes on the admin page
add_action( 'admin_init', 'mt_admin_init' );
// use the function
function mt_admin_init(){
add_meta_box(
'mt_first_metabox', // $id
'First Metabox', // $title
'mt_first_metabox', // $callback
'mythings', // $page /* stick with $post_type for now */
'normal', // $context /* 'normal' = main column. 'side' = sidebar */
'high' // $priority /* placement on admin page */
);
/* ADD ANOTHER META BOX HERE */
// design the first metabox
function mt_first_meta() {
global $post;
$custom = get_post_custom($post->ID);
$mt_field_one = $custom['mt_field_one'][0];
$mt_field_two = $custom['mt_field_two'][0];
// etcetera, etcetera
?> /* close the php tag to create your metabox layout with HTML */
<div class="wrap">
<p><label>My Text Input:</label><br />
<input name="mt_field_one" value="<?php echo $mt_field_one; ?>" /></p>
<p><label>My Textarea:</label><br />
<textarea name="mt_field_two"><?php echo $mt_field_one; ?></textarea></p>
</div><!-- end .wrap -->
<?php // reopen the php tag to continue adding functions
}
/* DESIGN ANOTHER META BOX HERE */
Part IV: Save Your Data
Here is the best part -- making it work.
// add your data-saving function
add_action('save_post', 'mt_save_data');
// use your function
function mt_save_data(){
global $post;
update_post_meta($post->ID, 'mt_field_one', $_POST['mt_field_one']);
update_post_meta($post->ID, 'mt_field_two', $_POST['mt_field_two']);
/* INCLUDE FIELDS FROM ALL OF YOUR META BOXES HERE */
} // end mt_save_data() function
Now test it out by filling in your fields on the admin page. Click save and watch your entries not disappear. If it works, you have earned your inflated sense of accomplishment.
There is plenty more functionality to play around with, but I must save that for my next post as this has gotten rather long.
How to change your password in MySQL
Need to change your password in MySQL? It’s pretty simple. Here is the command:
mysql> flush privileges;
How to backup to Amazon S3
Need to backup your Linux server files and databases to Amazon S3? Here is a great tool – http://s3tools.org/download
Follow the install instructions.
Once you set up your S3 bucket, you can use this bash script to copy files to the S3 bucket:
#!/bin/sh
#
## Lanexa.net - file name = BACKUP_s3.sh
## backup script to push archive files to Amazon S3 bucket
## 2012-01-04
#
# define where your backup files are stored locally on your server
FILEDIR=/BACKUP/files/
DBDIR=/BACKUP/mysql/
#
cd $FILEDIR
#
# use s3cmd to upload files to S3 instance
s3cmd put FILENAME s3://BUCKET-NAME/
#
cd $DBDIR
s3cmd put DATABASES s3://BUCKET-NAME/
#
# email a note to yourself that backup is complete
mail -s "backup files and databases copied to S3" youremail@address.com
Create a WordPress Child-theme on Thematic framework
I’m a huge fan of ThemeShaper‘s Thematic base theme, by Ian Stewart. After spending some time getting to know it, I have very little reason to start my custom themes from scratch. Since coming to understand the structure, I have yet to feel limited by it. View a diagram of the Thematic structure here. After a few projects, you’ll learn to see that plain white wireframe as an endless ocean of all possibility.
Obviously, start by installing the latest version of Thematic. Then decide whether you need a simple standard child theme, or a highly customized child theme.
Standard Sub-theme: The developers kindly offer a convenient way to implement a standard child-theme. From your FTP client:
- Navigate to wordpress/wp-content/themes/thematic
- Duplicate the directory thematicsamplechildtheme, copy it into the themes directory, and rename it to your liking.
- Go inside your child-theme directory, open the style.css, and edit the info found in the head of the document accordingly.
At this point, you should be able to activate your child-theme from the WordPress backend. Have at it!
Custom Sub-theme: For complete control over the design, you will want to override many Thematic files. To do so:
- Duplicate the thematic directory and rename it accordingly
- Open your new style.css, and delete the contents.
- Replace the contents with something like this:
/*
Theme Name: Custom Child Theme
Theme URI:
Description: A Child Theme on Thematic framework.
Author: Your Name
Author URI: http://yourdomain.com/
Template: thematic
Version: 1.0
Tags: Thematic
.
Thematic is © Ian Stewart http://themeshaper.com/
.
*/
@import url('../thematic/style.css');
*Note: The document head is the same as in their standard child theme style.css.
*Note: We are importing the main stylesheet from the parent theme.
- Open your new functions.php, and delete the contents.
- Optionally, you can replace the contents with something like this:
<?php
//
// Custom Child Theme Functions
//
// I've included a "commented out" sample function below that'll add a home link to your menu
// More ideas can be found on "A Guide To Customizing The Thematic Theme Framework"
// http://themeshaper.com/thematic-for-wordpress/guide-customizing-thematic-theme-framework/
// Adds a home link to your menu
// http://codex.wordpress.org/Template_Tags/wp_page_menu
//function childtheme_menu_args($args) {
// $args = array(
// 'show_home' => 'Home',
// 'sort_column' => 'menu_order',
// 'menu_class' => 'menu',
// 'echo' => true
// );
// return $args;
//}
//add_filter('wp_page_menu_args','childtheme_menu_args');
// Unleash the power of Thematic's dynamic classes
//
// define('THEMATIC_COMPATIBLE_BODY_CLASS', true);
// define('THEMATIC_COMPATIBLE_POST_CLASS', true);
// Unleash the power of Thematic's comment form
//
// define('THEMATIC_COMPATIBLE_COMMENT_FORM', true);
// Unleash the power of Thematic's feed link functions
//
// define('THEMATIC_COMPATIBLE_FEEDLINKS', true);
?>
*Note: This this the content offered in functions.php of the Thematic sample child theme.
Now you can also delete the library directory. You can build your own eventually, but this particular library must stay unique to the parent theme.
By copying over the Thematic files, you now have a duplicate theme overriding the parent, allowing you to make all the changes you want without harming the original.
Lastly, Thematic’s developers recommend copying their default.css into your style.css if you are going to be making major changes.
- From your FTP client, navigate to themes/thematic/library/styles/.
- Open default.css, and copy the contents.
- Go back to edit your style.css, and paste in the copied contents at the bottom.
And there you have it — a major head start on a highly customizable theme.
How to import your .sql into a MySQL database
How to import your db_backup.sql into an empty database:
mysql -u mysql_user -p db_name < /path/to/db_backup.sqlHow to export your MySQL database using mysqldump
Use your command line to backup your mysql database by exporting it to an .sql file. All you need to complete this task is shell access & a mysql account.
A major use for this command is to easily migrate your sites from one server to another. Since this is often part of a larger process, I like to decide ahead of time which directory will contain this file. So I’ll start by navigating to my desired directory and scoping it out:
cd /path/to/dir/; ls -alNow that you’re sure about using this directory. Here is the basic mysqldump command:
mysqldump db_name > db_backup.sqlBut, depending on your level of access, you may need to modify it:
mysqldump -u mysql_user -p db_name > db_backup.sqlEnter password:
After entering your mysql password, a file called db_backup.sql will be created in the default location, which is your current directory (three cheers for planning ahead!).
Of course, we could have just as easily added a location statement within the command:
mysqldump -u mysql_user -p db_name > /path/to/dir/db_backup.sqlBut, you’re going to want to cd there anyways, just to verify that everything’s in order
Be sure to browse our related posts describing how to get migrate files from one server to another, and how to import an .sql file into an empty MySQL databse.
wget the latest WordPress installed – pronto!
It’s so flippin’ fast! Forget about FTP-ing…
Step 1: wget it.
wget http://wordpress.org/latest.tar.gzThis command will place the file in your current directory. You may plan on unpacking & installing in multiple directories, so you may want to cd to the parent directory of those locations. Plus, if you choose this method to get the next latest version, you can wget it in the same directory and override the previous version.
Step 2: Copy it to your desired directory
cp latest.tar.gz /path/to/your/directory;Step 3: Go to that directory
cd /your/directoryStep 4: Verify that it’s there
lslatest.tar.gz
Step 5: gunzip it
gunzip latest.tar.gzStep 6: Unpack the tar ball
tar -xvf latest.tar*Note: -xvf combines 3 options. -x extracts the file from the archive. -v verbosely lists the files processed. -f uses the archive file.
Step 7: Verify that the wordpress directory is now there…
lswordpress
Presto! Now just set up the mysql database, edit wp-config.php, and go to http://yourdomain.com/wordpress/wp-admin/install.php to complete the final steps.
Get More out of WordPress’ Link Categories
The WordPress platform comes with an intriguing – yet often neglected – link managing feature in the Dashboard menu called Links. What’s intriguing is the potential power of this feature, particularly with respect to Link Categories. I emphasize potential power because it’s stock usage is currently limited to a sidebar widget. As Lanexa.net has recently been tasked with redesigning a site that maintains a substantial amount of external links, this article will demonstrate an easy way to increase the functionality of the link managing feature – by creating a landing page for your Link Categories (a.k.a. Bookmarks), which can be accessed from your main menu.
Step-by-Step
1. Create Desired Categories. In the WordPress Dashboard, go to Links > Link Categories to create the Name & Slug of the the categories you will be using. It’s not important to complete this step right away, but you’ll want to get a few things in there so you’ll have something to display further on.
2. Decide which Page Template to Use. This example will use the theme’s default template called page.php. If you’re working on a live site and don’t want to risk screwing something up, you can copy this template file and rename it, i.e. page-bkmrks.php.
3. Create the Landing Page From the Dashboard, add a new page and title it what you will, i.e. Bookmarks Lading Page. Select the template you will be using and save the page. Make note of the permalink url, underneath the title, before leaving the page. I recommend using pretty permalinks, for added convenience (and a million other reasons).
4. Edit the Template. Good code-editing software – such as Coda – will allow you to log on to your server, locate the active theme folder, duplicate & rename the appropriate file (if necessary), and open it up for editing. All you have to do now is insert this simple hook into the content div:
<?php
if (is_page('bookmarks-landing-page')) {
wp_list_bookmarks();
}
?>
Note: Using pretty permalinks allows me to select the page by title.
5. Visit Your New Bookmarks Landing Page. You will notice that all your bookmarks are displayed on the page, organized under their category titles. If this is all you are looking to do, you are free to add this page to your main menu like you would any other. For more advanced options, read on (or search “wp_list_bookmarks“).
6. Select which Categories to Display. You can modify the above code in order to customize which link categories will be displayed on which page:
<?php
if (is_page('bookmarks-landing-page')) {
wp_list_bookmarks('categorize=1&category=2,5');
}
?>
Note: categorize=1 will list the links beneath their corresponding category title, while categorize=0 – also categorize= (no value) – will list links under the general heading Bookmarks.
Note: category=2,5 calls the desired link categories by their ID numbers. A category’s ID number is revealed in the URL while editing it from the Dashboard.
Or, perhaps it makes more sense to exclude a category from the list:
<?php
if (is_page('bookmarks-landing-page')) {
wp_list_bookmarks('categorize=1&exclude_category=3,4,6');
}
?>
7. Display Different Categories on Different Pages. Create as many pages as you want (using the same template) to display as many different category combinations as you want. All you need to do is stack these conditional statements, one after the other:
<?php
if (is_page('bookmarks-landing-page')) {
wp_list_bookmarks();
}
?>
<?php
if (is_page('bookmarks-landing-page-2')) {
wp_list_bookmarks('categorize=0&exclude_category=3');
}
?>
<?php
if (is_page('bookmarks-landing-page-3')) {
wp_list_bookmarks('categorize=1&category=3,4,8');
}
?>
Note: A complete list of parameters is available in the WordPress Codex.
We hope to develop this functionality into a Plugin in the coming months. Until then, i hope you find this solution to be an easy-to-manage alternative.
Using .html in WordPress URLs
A great jazz drummer & friend of mine has a site with a beautiful custom design, yet he was having to rely on computer nerds to manage his content. After helping him with a few seemingly simple updates, it was obvious that his money & my time would be better spent enabling him to gain control over his content, so I offered to set him up in WordPress. The migration moved swiftly until hitting one snag – his custom Flash menu is hardwired with page links that use .html. Why use a Flash menu in the first place? Good quetion! But I can’t argue that it doesn’t look great, and he seemed intent on leaving the design as is.
Fortunately, 99% of this problem can be solved with a simple plugin – .html on Pages. Not only did it quickly enable the old links, it also saved me the trouble of setting up a bunch of redirects, which would have been necessary if using wordpress’ default URLs.
The final problem was with the Home page link. The Flash menu’s “Home” link is hardwired with index.html, and needed to be redirected to index.php. The solution for this is actually quite easy, as well. With hidden files turned on, locate the .htaccess file within the wordpress folder, installed on your server. Just insert this bit of code above anything else:
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html?$ / [NC,R,L]
View the results and check out some incredible music at timdrums.com.
WordPress Media: Increase Maximum Upload File Size
In WordPress Media Manager, the default settings for “maximum upload file size” seem to come out different for each installation, depending on the server. Most often, the max size is descent enough to live with, but after a recent install was only offering an insultingly low 2MB, I figured it’s best to be prepared to increase this value quickly & painlessly.
* Note: There’s also a chance that your hosting provider has the security for these parameters locked down pretty tight. If you try all of these steps and nothing is changed, you may need to contact your host and ask them nicely to do this for you.
Step-by-Step
1. Locate a file called php.ini. If you have SSH access, that’s great. You may find it with this:
php -i | grep php.ini
Otherwise, logon to your server via your FTP client and look in the root folder, as well as public_html. Don’t worry if you can’t find it – you can make one yourself by creating a text file and saving it as php.ini.
2. Insert the following text into the php.ini file:
memory_limit = 100M
upload_max_filesize = 64M
post_max_size = 64M
file_uploads = On
Go ahead and change the numeric values to your preferences.
3. Place the modified file. There are a number of locations to place the file, and different things seem to work for different people. If you modified a pre-existing file, try putting it back where you found it. Of course I recommend what worked for me, which is placing it inside the /wordpress/wp-admin folder. This may also be desirable because it will only affect that area of your site.
4. Modify wp-config.php. Add the following code to wp-config.php in order to match the desired file size:
/* Increases max file size for uploads */
define('WP_MEMORY_LIMIT', '64M');
Again, go ahead and change the numeric value to fit your preference.
5. Troubleshooting. If it doesn’t work right away, be sure to experiment with the location of the php.ini. One of these four locations should work: Root folder, public_html, wordpress (your wordpress install), or wordpress/wp-admin. In some cases, the .ini file may need to be renamed to php5.ini. Try both files in each location until the WordPress Media Manager reads “Maximum upload file size: 64MB”.









