Пользовательские шаблоны типов сообщений из папки плагинов?

57

Я хотел бы предложить свой тип поста в качестве плагина, чтобы люди могли использовать его, не касаясь папки своей темы. Но пользовательские шаблоны типов записей, такие как single-movies.php, находятся в папке темы. Есть ли способ заставить WP проверять наличие одного файла movies.php в папке плагина? Зацепить функцию в иерархии файлов ? Или get_template_directory (); ?

nathanbweb
источник

Ответы:

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;

}
Bainternet
источник
Это потрясающий ответ. Пожалуйста, поделитесь, где я могу получить все доступные шаблоны, такие как single_template.
Гоури
6
@gowri Фильтр вызывается get_query_template()функцией. Это переменная ловушка, поэтому первая часть {$type}_templateизменяется в зависимости от того, какой параметр передан этой функции. Смотрите wp-includes / template.php для некоторых распространенных
shea
Этот урок охватывает хук single_template с хорошим объяснением. Как только вы поймете хуки, комментарий @ shea предлагает более простой подход, чем ответ @ Bainternet, используя add_filter( 'single-movies_template', 'my_custom_template' );как в связанном руководстве. (Этот вопрос закрыт для новых ответов, поэтому я не могу добавить его самостоятельно.)
Грег
2
Вы можете заменить PLUGIN_PATHна, plugin_dir_path( __FILE__ )а затем удалить первую косую черту из вашего имени файла. Полный путь будет выглядеть примерно так:return plugin_dir_path( __FILE__ ) . 'Custom_File.php';
Frits
1
PLUGIN_PATH выдал ошибку, вот отличный пост, который показывает, как это сделать, и он работал для меня из коробки: wpsites.net/free-tutorials/…
Натан
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');

Теперь вы можете позволить пользователям плагина скопировать шаблон из вашего плагина в свою тему, чтобы переопределить его.

В этом примере шаблоны должны находиться в корневом каталоге плагина и темы.

campsjos
источник
1
Использование locate_templateвместо get_stylesheet_directoryзвучит как более чистый вариант для меня (находится здесь: code.tutsplus.com/tutorials/… ).
Феликс
1
Обновленный ответ не работает, принятый ответ (или ваш старый ответ) работает.
Эдвард
2
Вы правы, @Eward, это было ужасное обновление. Я обновил его снова с предложением Феликса. Также на этот раз я проверил код перед публикацией :)
campsjos
4

Я хотел бы отметить, что когда вы используете для этого метод фильтра, чрезвычайно важно расставить приоритеты фильтра следующим образом:

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

Если вы этого не сделаете, иногда WP будет пытаться перепроверить после этого фильтра. Вытаскивал мои волосы из-за этого около 2 часов.

RBizzle
источник
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');
pixelngrain
источник
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;
}
DigitalDesignDj
источник
1
Это не проверяет, присутствует ли single-cpt.php в дочернем элементе или в теме. Он проверяет только файл single.php, который всегда будет присутствовать в любых темах.
newpxsn
Правильно, когда я писал это, я использовал действительно голую тему, должен быть лучший способ!
DigitalDesignDj