How to create a custom post type for a portfolio in WordPress

Michael T Dec 17, 2024 Custom Post Types
I want to show my work on my site in a special way. How can I do this?
What steps should I follow to register a custom post type in WordPress specifically for a portfolio, ensuring that it supports custom fields, taxonomies, and has appropriate capabilities?
Andy answered Dec 17, 2024

Let's create a portfolio custom post type in WordPress! Here's how to do it step by step.

Basic Setup

First, let's register the portfolio custom post type. Add this code to your theme's functions.php file or in a custom plugin:

Basic portfolio post type registration:

function create_portfolio_post_type() {
    $labels = array(
        'name'               => 'Portfolio',
        'singular_name'      => 'Portfolio Item',
        'add_new'           => 'Add New Item',
        'add_new_item'      => 'Add New Portfolio Item',
        'edit_item'         => 'Edit Portfolio Item',
        'view_item'         => 'View Portfolio Item',
        'search_items'      => 'Search Portfolio',
        'menu_name'         => 'Portfolio'
    );

    $args = array(
        'labels'              => $labels,
        'public'              => true,
        'has_archive'         => true,
        'menu_icon'           => 'dashicons-format-gallery',
        'supports'            => array('title', 'editor', 'thumbnail', 'excerpt'),
        'show_in_rest'        => true, // Enables Gutenberg editor
        'rewrite'             => array('slug' => 'portfolio')
    );

    register_post_type('portfolio', $args);
}
add_action('init', 'create_portfolio_post_type');

Adding Custom Taxonomies

Let's add categories and tags for better organization:

Register portfolio taxonomies:

function create_portfolio_taxonomies() {
    // Categories
    register_taxonomy('portfolio_category', 'portfolio', array(
        'label'        => 'Portfolio Categories',
        'hierarchical' => true,
        'show_in_rest' => true,
        'rewrite'      => array('slug' => 'portfolio-category')
    ));

    // Tags
    register_taxonomy('portfolio_tag', 'portfolio', array(
        'label'        => 'Portfolio Tags',
        'hierarchical' => false,
        'show_in_rest' => true,
        'rewrite'      => array('slug' => 'portfolio-tag')
    ));
}
add_action('init', 'create_portfolio_taxonomies');

Adding Custom Fields

For custom fields, you have two options:

  1. Use Advanced Custom Fields (ACF) plugin
  2. Register custom meta fields manually

Here's how to add custom fields manually:

Register custom meta fields:

function register_portfolio_meta() {
    register_post_meta('portfolio', 'client_name', array(
        'type'         => 'string',
        'single'       => true,
        'show_in_rest' => true,
    ));
    
    register_post_meta('portfolio', 'project_url', array(
        'type'         => 'string',
        'single'       => true,
        'show_in_rest' => true,
    ));
}
add_action('init', 'register_portfolio_meta');

Best Practices and Security Considerations

  1. Flush Rewrite Rules: After adding the custom post type, visit Settings > Permalinks to refresh URL structure.

  2. Capabilities: Use specific capabilities for your post type:

Add custom capabilities:

function add_portfolio_capabilities() {
    $role = get_role('administrator');
    
    $capabilities = array(
        'edit_portfolio',
        'edit_portfolios',
        'edit_others_portfolios',
        'publish_portfolios',
        'read_portfolio',
        'read_private_portfolios',
        'delete_portfolio'
    );

    foreach ($capabilities as $cap) {
        $role->add_cap($cap);
    }
}
register_activation_hook(__FILE__, 'add_portfolio_capabilities');

Recommended Plugins

  1. Advanced Custom Fields (ACF): Essential for adding complex custom fields

  2. Custom Post Type UI: For managing custom post types through admin interface

Common Pitfalls to Avoid

  1. Don't forget to flush rewrite rules after registration
  2. Ensure unique post type and taxonomy names
  3. Back up capabilities before modifying them
  4. Consider translation support with text domains

Display Portfolio Items

Basic template code for displaying portfolio items:

$args = array(
    'post_type' => 'portfolio',
    'posts_per_page' => -1,
    'orderby' => 'date',
    'order' => 'DESC'
);

$portfolio_items = new WP_Query($args);

if ($portfolio_items->have_posts()) :
    while ($portfolio_items->have_posts()) : $portfolio_items->the_post();
        ?>
        <div class="portfolio-item">
            <h2><?php the_title(); ?></h2>
            <?php if (has_post_thumbnail()) : ?>
                <?php the_post_thumbnail('large'); ?>
            <?php endif; ?>
            <?php the_excerpt(); ?>
        </div>
        <?php
    endwhile;
    wp_reset_postdata();
endif;

Remember to style your portfolio items using CSS and consider using masonry or grid layouts for better presentation.