プラグインフォルダーからのカスタム投稿タイプテンプレート?


57

カスタム投稿タイプをプラグインとして提供したいので、テーマフォルダーに触れることなく使用できます。ただし、single-movies.phpなどのカスタム投稿タイプテンプレートはテーマフォルダーにあります。プラグインのフォルダーでWPにsingle-movies.phpをチェックさせる方法はありますか?Filer Hierarchyに関数をフックしますか?またはget_template_directory(); ?

回答:


90

single_templateフィルターフックを使用できます。

/* Filter the single_template with our custom function*/
add_filter('single_template', 'my_custom_template');

function my_custom_template($single) {

    global $post;

    /* Checks for single template by post type */
    if ( $post->post_type == 'POST TYPE NAME' ) {
        if ( file_exists( PLUGIN_PATH . '/Custom_File.php' ) ) {
            return PLUGIN_PATH . '/Custom_File.php';
        }
    }

    return $single;

}

それは素晴らしい答えです。single_templateのような利用可能なすべてのテンプレートを取得できるかどうかを共有してください。
Gowri

6
@gowriフィルターはget_query_template()関数によって呼び出されます。これは変数フックであるため、最初の部分{$type}_templateは、その関数に渡されるパラメーターに応じて変わります。参照してください。WPは、含まれて/ template.phpいくつかの一般的なもののために
シア

このチュートリアルでは、single_templateフックについて説明します。フックを理解すると、@ sheaのコメントはadd_filter( 'single-movies_template', 'my_custom_template' );、リンクされたチュートリアルのように、@ Bainternetの答えよりも簡単なアプローチを提案します。(この質問は新しい回答に閉じられているため、単独で追加することはできません。)
グレッグペラム

2
置き換えPLUGIN_PATHplugin_dir_path( __FILE__ )から、ファイル名の最初のスラッシュを削除できます。完全なパスは次のようになりますreturn plugin_dir_path( __FILE__ ) . 'Custom_File.php';
。– Frits

1
PLUGIN_PATHがエラーをスローしました。これを行う方法を示した素晴らしい投稿があります。これ
Nathan

22

更新された回答

より簡潔で短いバージョン。

function load_movie_template( $template ) {
    global $post;

    if ( 'movie' === $post->post_type && locate_template( array( 'single-movie.php' ) ) !== $template ) {
        /*
         * This is a 'movie' post
         * AND a 'single movie template' is not found on
         * theme or child theme directories, so load it
         * from our plugin directory.
         */
        return plugin_dir_path( __FILE__ ) . 'single-movie.php';
    }

    return $template;
}

add_filter( 'single_template', 'load_movie_template' );

古い答え

テーマフォルダーのカスタム投稿タイプ固有のテンプレートのチェックを@Brainternetの回答に追加しました。

function load_cpt_template($template) {
    global $post;

    // Is this a "my-custom-post-type" post?
    if ($post->post_type == "my-custom-post-type"){

        //Your plugin path 
        $plugin_path = plugin_dir_path( __FILE__ );

        // The name of custom post type single template
        $template_name = 'single-my-custom-post-type.php';

        // A specific single template for my custom post type exists in theme folder? Or it also doesn't exist in my plugin?
        if($template === get_stylesheet_directory() . '/' . $template_name
            || !file_exists($plugin_path . $template_name)) {

            //Then return "single.php" or "single-my-custom-post-type.php" from theme directory.
            return $template;
        }

        // If not, return my plugin custom post type template.
        return $plugin_path . $template_name;
    }

    //This is not my custom post type, do nothing with $template
    return $template;
}
add_filter('single_template', 'load_cpt_template');

これで、プラグインユーザーがテンプレートをプラグインからテーマにコピーして上書きできるようになりました。

この例では、テンプレートはプラグインとテーマの両方のルートディレクトリに存在する必要があります。


1
よりクリーンなオプションのような音のlocate_template代わりに使用get_stylesheet_directoryします(code.tutsplus.com/tutorials/…にあります)。
フェリックス

1
更新された回答は機能せず、受け入れられた回答(または以前の回答)が機能します。
エドワード

2
あなたは正しい、@ Edward、それは恐ろしい更新でした。Felixの提案で再度更新しました。また、今回は投稿する前にコードをテストしました:)
campsjos

4

このためにフィルターメソッドを使用している場合、次のようにフィルターに優先順位を付けることが非常に重要であることを指摘したいと思います。

add_filter('single_template', 'my_custom_template', 99);

これを行わないと、WPはこのフィルターの後に再チェックを試みることがあります。このために2時間ほど髪を引っ張っていました。


0

プラグインに使用しているより良い方法があります。

以下のよう@campsjosは言及し、ここで、代わりにファイルの存在チェックを、あなたは確認することができlocate_template、そのテーマのオーバーライドテンプレートファイルにチェックします。これは非常に明白です。

function my_plugin_templates() {
    if (is_singular('movie')) {
        if (file_exists($this->template_dir . 'single-movie.php')) {
            return $this->template_dir . 'single-movie.php';
        }
    }
}

template_include上記のコードをロードするには、フィルターフックを使用します。

add_filter('template_include' , 'my_plugin_templates');

0

このページのおかげで、私は同じ質問を解決できました。

参考までに、これは私がやったことです:

function pluginName_myposttype_single_template($single_template) {
  $myposttype_template = PLUGIN_DIR . 'templates/single-myposttype.php';
  return get_post_type() === 'myposttype' && file_exists($myposttype_template) ? $myposttype_template : $single_template;
}
add_filter('single_template', 'pluginName_myposttype_single_template');

{$ type} _templateフィルターフックが機能しませんでした

function pluginName_myposttype_single_template($single_template) {
  $myposttype_template = PLUGIN_DIR . 'templates/single-myposttype.php';

  if ( file_exists($myposttype_template) ) {
    $single_template = $myposttype_template;
  }
  return $single_template;
}
add_filter('single-myposttype_template', 'pluginName_myposttype_single_template');

-2

上記は素晴らしい答えですが、$ single varをチェックすることで、テーマ/子テーマによって提供されているテンプレートをオーバーライドできます。

/* Filter the single_template with our custom function*/
add_filter('single_template', 'your_cpt_custom_template');

function your_cpt_custom_template( $single ) {
    global $wp_query, $post;
    /* Checks for single template by post type */
    if ( !$single && $post->post_type == 'cpt' ) {
        if( file_exists( plugin_dir_path( __FILE__ ) . 'single-cpt.php' ) )
            return plugin_dir_path( __FILE__ ) . 'single-cpt.php';
    }
    return $single;
}

1
これは、single-cpt.phpが子またはテーマに存在するかどうかをチェックしません。どのテーマにも常に存在するsingle.phpに対してのみチェックします。
newpxsn

そうです、私がこれを書いたとき、私は本当に裸のテーマを使用していました、より良い方法がなければなりません!
DigitalDesignDj
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.