Шаблоны Произвольных Типов Записей из Папки Плагина?

16 мая 2011 г., 16:16:45
Просмотры: 53.9K
Голосов: 82

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

0
Все ответы на вопрос 8
7
121

Вы можете использовать хук фильтра single_template.

/* Фильтруем single_template с нашей пользовательской функцией */
add_filter('single_template', 'my_custom_template');

function my_custom_template($single) {

    global $post;

    /* Проверяем шаблон для одиночной записи по типу поста */
    if ( $post->post_type == 'НАЗВАНИЕ ТИПА ЗАПИСИ' ) {
        if ( file_exists( PLUGIN_PATH . '/Custom_File.php' ) ) {
            return PLUGIN_PATH . '/Custom_File.php';
        }
    }

    return $single;

}
16 мая 2011 г. 16:41:53
Комментарии

Это потрясающий ответ. Пожалуйста, поделитесь, где можно найти все доступные хуки шаблонов, такие как single_template.

Gowri Gowri
2 мая 2013 г. 21:18:00

@gowri Фильтр вызывается функцией get_query_template(). Это переменный хук, поэтому первая часть {$type}_template меняется в зависимости от параметра, передаваемого в эту функцию. Смотрите wp-includes/template.php для некоторых распространённых примеров.

shea shea
7 мая 2013 г. 12:42:24

Это руководство хорошо объясняет хук single_template. Как только вы разберётесь с хуками, комментарий @shea предлагает более простой подход по сравнению с ответом @Bainternet, используя add_filter( 'single-movies_template', 'my_custom_template' ); как в связанном руководстве. (Этот вопрос закрыт для новых ответов, поэтому я не могу добавить его отдельно.)

Greg Perham Greg Perham
26 сент. 2017 г. 07:34:29

Вы можете заменить PLUGIN_PATH на plugin_dir_path( __FILE__ ), а затем убрать первый слеш из имени вашего файла. Полный путь будет выглядеть примерно так: return plugin_dir_path( __FILE__ ) . 'Custom_File.php';

Frits Frits
13 февр. 2018 г. 08:49:06

Возможно, сейчас PLUGIN_PATH называется WP_PLUGIN_DIR.

Hans Dash Hans Dash
26 мар. 2019 г. 18:19:43

PLUGIN_PATH вызывал ошибку, вот отличная статья, которая показывает, как это сделать, и у меня сработало сразу: https://wpsites.net/free-tutorials/load-single-template-from-plugin-for-different-post-types/

Nathan Nathan
2 мая 2019 г. 23:19:24

есть ли фильтр только для пользовательского типа записи?

v3nt v3nt
6 сент. 2019 г. 11:46:02
Показать остальные 2 комментариев
3
40

Обновленный ответ

Более чистая и короткая версия.

function load_movie_template( $template ) {
    global $post;

    if ( 'movie' === $post->post_type && locate_template( array( 'single-movie.php' ) ) !== $template ) {
        /*
         * Это запись типа 'movie'
         * И шаблон 'single movie template' не найден в
         * директориях темы или дочерней темы, поэтому загружаем его
         * из директории нашего плагина.
         */
        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;

    // Это запись типа "my-custom-post-type"?
    if ($post->post_type == "my-custom-post-type"){

        // Путь к вашему плагину
        $plugin_path = plugin_dir_path( __FILE__ );

        // Название шаблона для одиночной записи пользовательского типа
        $template_name = 'single-my-custom-post-type.php';

        // Существует ли специфичный шаблон для моего типа записи в папке темы? Или его нет и в моем плагине?
        if($template === get_stylesheet_directory() . '/' . $template_name
            || !file_exists($plugin_path . $template_name)) {

            // Тогда возвращаем "single.php" или "single-my-custom-post-type.php" из директории темы.
            return $template;
        }

        // Если нет, возвращаем шаблон из плагина.
        return $plugin_path . $template_name;
    }

    // Это не мой пользовательский тип записи, ничего не делаем с $template
    return $template;
}
add_filter('single_template', 'load_cpt_template');

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

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

15 янв. 2016 г. 11:45:36
Комментарии

Использование locate_template вместо get_stylesheet_directory кажется мне более аккуратным решением (нашел здесь: http://code.tutsplus.com/tutorials/a-guide-to-wordpress-custom-post-types-creation-display-and-meta-boxes--wp-27645).

Felix Felix
14 июн. 2016 г. 21:11:35

Обновленный ответ не сработал, принятый ответ (или ваш старый ответ) работает.

Edward Edward
29 мар. 2018 г. 17:43:43

Ты прав, @Edward, это было ужасное обновление. Я снова обновил его с учетом предложения Felix. На этот раз я также протестировал код перед публикацией :)

campsjos campsjos
3 апр. 2018 г. 18:40:46
0

Хочу обратить внимание, что при использовании метода фильтрации крайне важно установить приоритет фильтра следующим образом:

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

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

14 дек. 2016 г. 18:33:50
0

В своих плагинах я обычно использую locate_template(), что позволяет переопределять шаблоны плагина, копируя их в текущую тему:

function templateInclude(string $template): string
{
    if (is_single() && get_query_var('post_type') === 'custom_post_type') {
        $templates = [
            'single-custom_post.php',
            'templates/single-custom_post.php'
        ];
        $template = locate_template($templates);
        if (!$template) {
            $template = __DIR__ . '/templates/single-custom_post.php';
        }
    }
    return $template;
}

add_filter('template_include', 'templateInclude');

Теперь пользователь может переопределить шаблон плагина, скопировав его из папки плагина templates/single-custom_post.php и разместив его либо непосредственно в корне, либо в папке templates активной темы.

Полагаю, аналогичный подход можно использовать и с фильтром single_template.

16 дек. 2021 г. 21:38:20
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');
1 авг. 2019 г. 08:39:55
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');
20 окт. 2019 г. 02:21:03
0

Этот вариант сработал для меня, попробуйте его. Спасибо.
Шаблоны загружаются в файл CPT, который находится по пути:
custom_plugin -> app -> cpt -> cpt_article.php
Шаблон расположен в:
custom_plugin -> app -> templates

add_filter( 'single_template', 'load_my_custom_template', 99, 1 );
 function load_custom_templates($single_template) {
   global $post;
   if ($post->post_type == 'article' ) {
   $single_template = trailingslashit( plugin_dir_path( __FILE__ ) .'app/templates' ).'single_article.php';
  }
   return $single_template;
}
11 июл. 2020 г. 02:59:54
2
-2

Выше приведен отличный ответ, но проверка переменной $single позволяет шаблону переопределить шаблон, если он предоставлен темой/дочерней темой.

/* Фильтруем single_template с помощью нашей пользовательской функции */
add_filter('single_template', 'your_cpt_custom_template');

function your_cpt_custom_template( $single ) {
    global $wp_query, $post;
    /* Проверяем шаблон для одиночной записи по типу записи */
    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;
}
19 окт. 2015 г. 19:47:59
Комментарии

Это не проверяет наличие файла single-cpt.php в дочерней теме или основной теме. Проверяется только файл single.php, который всегда присутствует в любых темах.

newpoison newpoison
28 окт. 2015 г. 22:01:47

Верно, когда я писал это, я использовал очень минималистичную тему. Должен быть более правильный способ!

DigitalDesignDj DigitalDesignDj
20 нояб. 2015 г. 23:19:20