I recently created an online course platform for a client. Usually I would turn to a dedicated course plugin to power courses with WordPress, but this client didn’t need the usual course platform logic surrounding payments and access logic to various programs. I always feel like less is best when it comes to code, why require the server to load more than it needs to?

Instead I decided to create a Hierarchical Custom Post Type which allowed us to create child pages for each post, and then perform a check in our template file to detect whether the post is a parent or a child. Depending on the answer, we could then import a different template part to output the content we need, though you could just as easily add the markup directly to the template file.

$post_current = get_post(); // get information on the current post

$args = array(
   'post_parent' => $parent_id, // the id of the parent post
   'posts_per_page' => -1, // to ensure we return every child post in the query
   'post_type' => 'courses', // our custom post type
);

$children = get_posts($args);
    
$is_child = false; // set child to false by default

// loop over posts and set is_child to true if the post is a child    
foreach ($children as $child) {
    if ( $child->ID == $post_current->post_parent ) {
        $is_child = true;
        break;
    }
}
    
if ($is_child) { // if the post is a child, include our template-part
    include(locate_template('inc/templates/course.php', false, false)); 
} else { // if the post is a parent, include an alternative template-part
    include(locate_template('inc/templates/chapter.php', false, false)); 
}

wp_reset_postdata();