fervor [>]CODING & CURIOSITY
FERVOR LEARNING SYSTEMTUTORIALS
← WordPress

WordPress / 8 MIN READ

Custom Posts Templating PHP

Templating custom posts with PHP

From the original Fervor library. Examples may use older package versions.

🌟 Building a Custom Post Type (CPT) in WordPress with PHP 🌟

WordPress allows you to go beyond posts and pages with Custom Post Types (CPTs)—perfect for adding unique content types like portfolios, events, recipes, or products. Let’s create one step by step! 🚀


📋 What is a Custom Post Type?

A Custom Post Type is a type of content different from standard WordPress posts or pages. Examples include:

  • Portfolios for showcasing your work.
  • Events for an event management website.
  • Products for an online store.

🔧 Step 1: Register a Custom Post Type

  1. Open your child theme folder.
  2. Locate the functions.php file.
  3. Add the following code to register your Custom Post Type (CPT):

Example: Registering a “Portfolio” CPT

function create_portfolio_cpt() {
    $labels = [
        'name' => 'Portfolios',
        'singular_name' => 'Portfolio',
        'menu_name' => 'Portfolios',
        'add_new_item' => 'Add New Portfolio',
        'edit_item' => 'Edit Portfolio',
        'new_item' => 'New Portfolio',
        'view_item' => 'View Portfolio',
        'all_items' => 'All Portfolios',
    ];

    $args = [
        'labels' => $labels,
        'public' => true,
        'has_archive' => true,
        'menu_icon' => 'dashicons-portfolio', // Admin menu icon
        'supports' => ['title', 'editor', 'thumbnail', 'custom-fields'],
        'rewrite' => ['slug' => 'portfolio'], // URL slug
    ];

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

🧩 Step 2: Customize Your CPT

Add Taxonomies (Optional)

Just like posts have categories and tags, you can add custom taxonomies to your CPT.

Example: Add “Project Type” Taxonomy to Portfolios

function create_portfolio_taxonomy() {
    $args = [
        'labels' => [
            'name' => 'Project Types',
            'singular_name' => 'Project Type',
            'search_items' => 'Search Project Types',
        ],
        'hierarchical' => true, // Works like categories
        'public' => true,
        'rewrite' => ['slug' => 'project-type'],
    ];

    register_taxonomy('project-type', ['portfolio'], $args);
}
add_action('init', 'create_portfolio_taxonomy');

Why It’s Cool:

  • Organize portfolios by type (e.g., “Web Design”, “Photography”).
  • Enhance filtering and display options for users.

🎨 Step 3: Add a Custom Archive Template

WordPress uses the template hierarchy to display CPTs. Create an archive template to control how your CPT archive appears.

  1. Create a File:
    Inside your child theme, create a file called archive-portfolio.php.

  2. Add Custom Layout:

<?php
get_header(); // Load the site header
?>
<div class="portfolio-archive">
    <h1>Our Portfolios</h1>
    <?php
    if (have_posts()) :
        while (have_posts()) : the_post();
    ?>
            <div class="portfolio-item">
                <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
                <?php the_post_thumbnail('medium'); ?>
                <p><?php the_excerpt(); ?></p>
            </div>
    <?php
        endwhile;
    else :
        echo '<p>No portfolios found.</p>';
    endif;
    ?>
</div>
<?php
get_footer(); // Load the site footer
?>

🔗 Step 4: Create a Custom Single Template

Want a unique layout for single portfolio items? Let’s make one!

  1. Create a File:
    Inside your child theme, create a file called single-portfolio.php.

  2. Add Custom Content:

<?php
get_header();
?>
<div class="portfolio-single">
    <h1><?php the_title(); ?></h1>
    <?php if (has_post_thumbnail()) : ?>
        <div class="portfolio-thumbnail">
            <?php the_post_thumbnail('large'); ?>
        </div>
    <?php endif; ?>
    <div class="portfolio-content">
        <?php the_content(); ?>
    </div>
    <div class="portfolio-meta">
        <p><strong>Project Type:</strong> <?php echo get_the_term_list(get_the_ID(), 'project-type', '', ', '); ?></p>
    </div>
</div>
<?php
get_footer();
?>

🎯 Step 5: Add CPT to Menus and Widgets

  • Go to Appearance > Menus in the WordPress admin.
  • Add your CPT archive (e.g., “Portfolios”) to the menu for easy navigation.
  • Use the Custom HTML widget to highlight specific portfolio items in a sidebar.

💡 Pro Tips for CPTs

1️⃣ Use Dashicons for Admin Menus

Add a slick WordPress icon to your CPT menu with menu_icon.

'menu_icon' => 'dashicons-portfolio',

2️⃣ Custom Fields for Extra Data

Use the Advanced Custom Fields (ACF) plugin to add fields like:

  • Client Name
  • Completion Date
  • Project URL

Display the fields in your template:

<div class="portfolio-details">
    <p>Client: <?php the_field('client_name'); ?></p>
    <p>Date: <?php the_field('completion_date'); ?></p>
    <p>URL: <a href="<?php the_field('project_url'); ?>"><?php the_field('project_url'); ?></a></p>
</div>

3️⃣ Custom Rewrite Rules

Want cleaner URLs? Use rewrite in register_post_type():

'rewrite' => ['slug' => 'work'],

This changes URLs from /portfolio/project-name to /work/project-name.


By default, WordPress searches only posts and pages. Add your CPTs like this:

function include_cpt_in_search($query) {
    if ($query->is_search && !is_admin()) {
        $query->set('post_type', ['post', 'page', 'portfolio']);
    }
    return $query;
}
add_filter('pre_get_posts', 'include_cpt_in_search');

5️⃣ CPT Pagination

For long archives, add pagination with paginate_links():

echo paginate_links([
    'total' => $wp_query->max_num_pages,
    'prev_text' => '« Previous',
    'next_text' => 'Next »',
]);

6️⃣ Block Editor Compatibility

Make your CPT Gutenberg-friendly by adding show_in_rest:

'show_in_rest' => true,

🎉 You Did It!

You’ve created a fully functional Custom Post Type in WordPress! Here’s what you’ve learned:

  1. How to register a CPT with PHP.
  2. Adding taxonomies for better organization.
  3. Customizing archive and single templates.
  4. Pro tips for extending functionality.

🚀 Next Steps:

  • Add custom taxonomies for more structure.
  • Explore custom meta boxes or use ACF for advanced fields.
  • Let me know if you want to learn about custom shortcodes, CPT filtering, or Gutenberg blocks next! 🛠️

Bonus Cool Stuff

🌟 Trendy Single Post Template for Your Custom Post Type (Portfolio) 🌟

Let’s design a modern and trendy template for a single portfolio post! This template will:

  • Highlight the project details (e.g., client name, project date).
  • Include a large hero section for the featured image.
  • Use a clean, minimalist layout perfect for showcasing projects.
  • Look great with mobile-friendly, responsive styles.

🎨 Step 1: Create the Template File

  1. In your child theme, create a file called single-portfolio.php.
  2. Add the following code as the base structure:
<?php
get_header(); // Load the site header
?>
<div class="portfolio-single trendy-template">
    <?php if (has_post_thumbnail()) : ?>
        <div class="portfolio-hero" style="background-image: url('<?php echo get_the_post_thumbnail_url(get_the_ID(), 'full'); ?>');">
            <div class="portfolio-hero-overlay">
                <h1 class="portfolio-title"><?php the_title(); ?></h1>
            </div>
        </div>
    <?php endif; ?>

    <div class="portfolio-content-wrapper">
        <div class="portfolio-details">
            <h2>Project Details</h2>
            <ul>
                <li><strong>Client:</strong> <?php the_field('client_name'); ?></li>
                <li><strong>Date:</strong> <?php the_field('completion_date'); ?></li>
                <li><strong>Category:</strong> <?php echo get_the_term_list(get_the_ID(), 'project-type', '', ', '); ?></li>
                <li><strong>Website:</strong> <a href="<?php the_field('project_url'); ?>" target="_blank"><?php the_field('project_url'); ?></a></li>
            </ul>
        </div>

        <div class="portfolio-description">
            <h2>About the Project</h2>
            <?php the_content(); ?>
        </div>
    </div>
</div>
<?php
get_footer(); // Load the site footer
?>

🎨 Step 2: Add Modern Styling

Add the following CSS to your child theme’s style.css file to give it a trendy and responsive design:

/* General Styles */
.trendy-template {
    font-family: 'Arial', sans-serif;
    color: #333;
}

/* Hero Section */
.portfolio-hero {
    position: relative;
    height: 400px;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}

.portfolio-hero-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    justify-content: center;
    align-items: center;
}

.portfolio-title {
    color: #fff;
    font-size: 2.5rem;
    text-transform: uppercase;
    text-align: center;
    margin: 0;
}

/* Content Wrapper */
.portfolio-content-wrapper {
    max-width: 900px;
    margin: 30px auto;
    padding: 20px;
    background: #f9f9f9;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
    border-radius: 10px;
}

/* Details Section */
.portfolio-details h2 {
    font-size: 1.8rem;
    margin-bottom: 10px;
    color: #222;
}

.portfolio-details ul {
    list-style: none;
    padding: 0;
}

.portfolio-details li {
    margin-bottom: 10px;
    font-size: 1rem;
    line-height: 1.5;
}

.portfolio-details li a {
    color: #0073aa;
    text-decoration: none;
}

.portfolio-details li a:hover {
    text-decoration: underline;
}

/* Description Section */
.portfolio-description h2 {
    font-size: 1.8rem;
    margin-top: 30px;
    margin-bottom: 15px;
    color: #222;
}

.portfolio-description p {
    font-size: 1rem;
    line-height: 1.8;
}

/* Responsive Design */
@media (max-width: 768px) {
    .portfolio-hero {
        height: 250px;
    }

    .portfolio-title {
        font-size: 1.8rem;
    }

    .portfolio-content-wrapper {
        padding: 15px;
    }

    .portfolio-details h2,
    .portfolio-description h2 {
        font-size: 1.5rem;
    }
}

🎯 Step 3: Add Extra Polish

Custom Fonts

Use Google Fonts for a modern look. For example:

  1. Add this to your functions.php:

    function enqueue_trendy_template_styles() {
        wp_enqueue_style('google-fonts', 'https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600&display=swap', [], null);
    }
    add_action('wp_enqueue_scripts', 'enqueue_trendy_template_styles');
    
  2. Update your CSS to use the new font:

    font-family: 'Montserrat', sans-serif;
    

Icons for Project Details

Add icons next to each detail using Font Awesome or similar libraries.

  1. Enqueue Font Awesome in functions.php:

    function enqueue_fontawesome() {
        wp_enqueue_style('font-awesome', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css', [], null);
    }
    add_action('wp_enqueue_scripts', 'enqueue_fontawesome');
    
  2. Add icons in your details section:

    <li><i class="fas fa-user"></i> <strong>Client:</strong> <?php the_field('client_name'); ?></li>
    <li><i class="fas fa-calendar"></i> <strong>Date:</strong> <?php the_field('completion_date'); ?></li>
    <li><i class="fas fa-tags"></i> <strong>Category:</strong> <?php echo get_the_term_list(get_the_ID(), 'project-type', '', ', '); ?></li>
    <li><i class="fas fa-link"></i> <strong>Website:</strong> <a href="<?php the_field('project_url'); ?>" target="_blank"><?php the_field('project_url'); ?></a></li>
    

🎉 Features of This Template

1️⃣ Responsive Hero Section

  • Uses the featured image as a stunning full-width background.
  • Includes an overlay for better readability.

2️⃣ Highlight Project Details

  • Clearly displays key project information in a modern card-like design.

3️⃣ Minimalist Content Section

  • Keeps the focus on the content with clean typography and spacing.

4️⃣ Responsive Design

  • Looks great on all devices, from desktops to smartphones.

🚀 Next Steps

  1. Custom Styling: Play with colors, spacing, and fonts to match your brand.
  2. Enhance with Animation: Add CSS transitions or animations for hover effects and smooth scrolling.
  3. Add Related Projects Section: Showcase similar projects at the bottom of the page.
    <div class="related-projects">
        <h2>Related Projects</h2>
        <?php
        $related = new WP_Query([
            'post_type' => 'portfolio',
            'posts_per_page' => 3,
            'post__not_in' => [get_the_ID()],
            'tax_query' => [
                [
                    'taxonomy' => 'project-type',
                    'field' => 'slug',
                    'terms' => wp_get_post_terms(get_the_ID(), 'project-type', ['fields' => 'slugs']),
                ],
            ],
        ]);
        if ($related->have_posts()) :
            while ($related->have_posts()) : $related->the_post();
                echo '<h3><a href="' . get_permalink() . '">' . get_the_title() . '</a></h3>';
            endwhile;
            wp_reset_postdata();
        endif;
        ?>
    </div>
    

🔥 Final Thoughts

This trendy template elevates your portfolio to a professional, modern level. It’s minimalist, mobile-friendly, and customizable. Pair it with the rest of your custom post type setup for a sleek, cohesive website.

Keep your curiosity going.Explore more WordPress →
287 TUTORIALS · 22 TOPICSREADY