Apply a custom Template to a Custom Post Type from within a plugin

Here you are – a plugin that is registering a Custom Post Type (CPT) and pushing template file from the plugin for that particular CPT.

<?php
/**
 * Plugin Name: WPSE352898 Template Test
 * Author:      Mayeenul Islam
 * Author URI:  https://mayeenulislam.github.io
 */

/**
 * Register My Custom Post Type.
 */
function wpse352898_register_cpt() {
    register_post_type('mycpt', array(
        'labels' => array(
            'name'          => 'My CPT',
            'singular_name' => 'My CPT',
            'menu_name'     => 'My CPT',
        ),
        'public'              => true,
        'publicly_queryable'  => true,
        'exclude_from_search' => false,
        'has_archive'         => true,
        'query_var'           => true,
        'rewrite'             => true,
    ));
}

add_action( 'init', 'wpse352898_register_cpt' );

/**
 * Template loader
 *
 * @param string $template The template that is called.
 * 
 * @return string          Template, that is thrown per modification.
 */
function wpse352898_template_loader( $template ) {
    $find = array();
    $file="";
    if ( is_single() && 'mycpt' === get_post_type() ) {
        // Singular template for CPT 'mycpt' in a theme.
        $file="single-mycpt.php";
        $find[] = $file;
        // Directory in a theme, where user can define their custom template to override plugin imposed template.
        $find[] = 'mycpt-templates/' . $file;
    }
    if ( $file ) {
        $template = locate_template( array_unique( $find ) );
        if ( ! $template ) {
            // Load template file from the plugin under this directory.
            $template = untrailingslashit( plugin_dir_path( __FILE__ ) ) . '/templates/' . $file;
        }
    }
    return $template;
}

add_filter( 'template_include', 'wpse352898_template_loader' );

After activating the plugin you will need to flush rewrite rules manually by saving the form in Settings » Permalinks without any modification. But you can also flush the rewrite rules from the plugin on register_activation_hook (which is not shown here).

To display a template file from the plugin the plugin will look into the template here: <plugin>/templates/single-mycpt.php.

There will be provision to override the plugin imposed template from the active theme, where it will look into the overridden template here: <active-theme>/mycpt-templates/single-mycpt.php.

Hope it helps. 🙂