Как загрузить шаблон страницы из плагина?

9 февр. 2017 г., 15:21:00
Просмотры: 23.5K
Голосов: 13

Я хочу добавить шаблоны страниц в тему напрямую из плагина. Идея в том, чтобы шаблон отображался в выпадающем списке в разделе "Атрибуты страницы" (Page Attributes), и весь код должен находиться в плагине.

Есть ли какие-нибудь советы, как это реализовать?

0
Все ответы на вопрос 8
2
15

Вы можете использовать фильтр theme_page_templates для добавления шаблонов в выпадающий список шаблонов страниц следующим образом:

function wpse255804_add_page_template ($templates) {
    $templates['my-custom-template.php'] = 'Мой шаблон';
    return $templates;
    }
add_filter ('theme_page_templates', 'wpse255804_add_page_template');

Теперь WordPress будет искать файл my-custom-template.php в директории темы, поэтому вам нужно перенаправить его в директорию вашего плагина с помощью фильтра page_template вот так:

function wpse255804_redirect_page_template ($template) {
    if ('my-custom-template.php' == basename ($template))
        $template = WP_PLUGIN_DIR . '/mypluginname/my-custom-template.php';
    return $template;
    }
add_filter ('page_template', 'wpse255804_redirect_page_template');

Подробнее об этом можно прочитать здесь: Добавление пользовательского шаблона страницы программно

9 февр. 2017 г. 16:23:16
Комментарии

идеально! это именно то, что нужно.

smartcat smartcat
9 февр. 2017 г. 17:53:27

начиная с версии 4.7 WordPress, приведенный код не будет работать. Измените эту строку с 'if ('my-custom-template.php' == basename ($template))' на $post = get_post(); $page_template = get_post_meta( $post->ID, '_wp_page_template', true ); if ('my-custom-template.php' == basename ($page_template ))

Nirmal Goswami Nirmal Goswami
9 дек. 2017 г. 11:47:01
0

Это комбинация приведенного выше ответа и комментариев, которая в итоге сработала для меня.

Функция для добавления плагина в список доступных шаблонов:

function wpse255804_add_page_template ($templates) {
    $templates['my-custom-template.php'] = 'Мой шаблон';
    return $templates;
    }
add_filter ('theme_page_templates', 'wpse255804_add_page_template');


Функция для указания пути к шаблону внутри плагина:

function wpse255804_redirect_page_template ($template) {
    $post = get_post();
    $page_template = get_post_meta( $post->ID, '_wp_page_template', true );
    if ('my-custom-template.php' == basename ($page_template))
        $template = WP_PLUGIN_DIR . '/mypluginname/my-custom-template.php';
    return $template;
    }
add_filter ('page_template', 'wpse255804_redirect_page_template');
9 окт. 2018 г. 22:29:45
1

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

Уверен, есть способ сделать это лучше, но у меня сработало.

/**
 * Загрузка шаблона через плагин
 */
function yourname_add_page_template ($templates) {
    $templates['page-one.php'] = 'Название здесь Один';
    $templates['page-two.php'] = 'Название здесь Два';
    $templates['page-three.php'] = 'Название здесь Три';
    return $templates;
}
add_filter ('theme_page_templates', 'yourname_add_page_template');

function yourname_redirect_page_template ($template) {
    $post = get_post();
    $page_template = get_post_meta( $post->ID, '_wp_page_template', true );
    if ('page-one.php' == basename ($page_template)) {
        $template = WP_PLUGIN_DIR . '/pluginname/templates/page-one.php';
        return $template;
    }
    elseif ('page-two.php' == basename ($page_template)) {
        $template = WP_PLUGIN_DIR . '/pluginname/templates/page-two.php';
        return $template;
    }
    elseif ('page-three.php' == basename ($page_template)) {
        $template = WP_PLUGIN_DIR . '/pluginname/templates/page-three.php';
        return $template;
    }
}
add_filter ('page_template', 'yourname_redirect_page_template');

1 июн. 2019 г. 07:55:55
Комментарии

Вы пропустили return $template, если он не соответствует ни одному из page-one/two/three

Rup Rup
4 нояб. 2022 г. 02:46:59
0

Из кодекса:

<?php 
   $templates = get_page_templates();
   foreach ( $templates as $template_name => $template_filename ) {
       echo "$template_name ($template_filename)<br />";
   }
?>

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

9 февр. 2017 г. 15:40:05
0

The below code snippet is very well thought out, it will try to look for a template in the plugin and if it can't find it there it will try to get it from the theme.

define( 'MY_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'MY_PLUGIN_TEMPLATE_DIR', MY_PLUGIN_DIR . '/templates/' );

add_filter( 'template_include', 'ibenic_include_from_plugin', 99 );

function ibenic_include_from_plugin( $template ) {

    $new_template = '';

    $provided_template_array = explode( '/', $template );

    // This will give us archive.php
    $new_template = end( $provided_template_array );

    // Define single and archive template for custom post type 'portfolio'
    if( is_singular('portfolio') ) {
        $new_template = 'single-portfolio.php';
    }

    if( is_post_type_archive( 'portfolio' ) ) {
        $new_template = 'archive-portfolio.php';
    }

    $plugin_template = MY_PLUGIN_TEMPLATE_DIR . $new_template;

    if( file_exists( $plugin_template ) ) {
        return $plugin_template;
    }

    return $template;
}

Source: https://www.ibenic.com/include-or-override-wordpress-templates/

26 февр. 2020 г. 01:14:55
4

Обновление за 2022 год: Приведенный ниже код добавит шаблон в список шаблонов страниц и зарегистрирует его в файлах вашего плагина.

// ------------добавление шаблона в список шаблонов страниц------------
function register_custom_template_list ($templates) {
  // ------------регистрация отображаемого имени шаблона с именем файла------------
  $templates['my-template.php'] = 'Название моего шаблона';
  // ------------возврат списка шаблонов страниц с новым добавлением------------
  return $templates;
}
// ------------привязка шаблона страницы к списку шаблонов------------
add_filter('theme_page_templates', 'register_custom_template_list');

// ------------регистрация шаблона страницы в файле------------
function render_custom_template_archive ($template) {
  // ------------получение атрибутов текущей редактируемой страницы------------
  $post = get_post();
  $page_template = get_post_meta( $post->ID, '_wp_page_template', true );
  // ------------проверка, выбран ли шаблон для пользовательского шаблона------------
  if (basename ($page_template) == 'my-template.php'){
    // ------------регистрация файла шаблона страницы для страницы------------
    $template = dirname(__DIR__).'/path_to/my-template.php';
    // ------------отображение содержимого пользовательского шаблона------------
    return $template;
  } else {
    // ------------возврат выбранного шаблона, если пользовательский шаблон не выбран------------
    return $template;
  }
}
// ------------привязка шаблона страницы к файлу------------
add_filter('page_template', 'render_custom_template_archive');
3 нояб. 2022 г. 06:43:38
Комментарии

Это похоже на ответ TKEz. В чем разница?

Rup Rup
4 нояб. 2022 г. 02:45:10

@Rup Я добавил комментарии к коду, чтобы разница стала понятнее. Основное отличие в последней части "render_custom_template_archive". Оператор else гарантирует, что другие шаблоны страниц также могут загружаться. Принятый ответ/ответ TKEz сломал мой сайт на WP и заставил все страницы использовать мой кастомный шаблон. Мне пришлось полностью сбросить сайт, чтобы он заработал (к счастью, это был тестовый сайт).

sallycakes sallycakes
4 нояб. 2022 г. 19:01:07

Оба варианта должны работать нормально в текущем виде, если только вы не добавите дополнительные фигурные скобки. Обе функции заканчиваются на return $template, который будет выполнен независимо от того, истинно условие или нет.

Rup Rup
5 нояб. 2022 г. 19:19:48

@Rup если посмотреть ответ TKEz; его оператор return находится только внутри оператора if, что вызывало проблемы на моем сайте

sallycakes sallycakes
5 нояб. 2022 г. 22:32:38
0

Теперь, когда WordPress поддерживает использование так называемых шаблонов страниц (Page Templates) и для других типов записей, обновлённый пример, который работает с постами, пользовательскими типами записей, а также страницами, может быть полезен.

/*
    Plugin Name: Example Plugin Templates
    Plugin URI: 
    Description: Загрузка шаблонов страниц (или типов записей) из плагина
    Version: 0.1
    Requires at least: 6.0
    Requires PHP: 7
    Author: t31os
    Author URI: 
    License: GPL v2 or later
    License URI: https://www.gnu.org/licenses/gpl-2.0.html
*/
namespace t31os\Plugin;

if( !defined('ABSPATH') )
    exit;

class Plugin_Templates {
    
    private $types;
    private $args;
    private $folder;
    private $templates = [
         'template-name-1.php' => 'Шаблон плагина 1'
        ,'template-name-2.php' => 'Шаблон плагина 2'
        ,'template-name-3.php' => 'Шаблон плагина 3'
    ];
    
    public function __construct() {
        // Хук с поздним приоритетом, чтобы плагины/темы успели зарегистрировать типы записей
        add_action( 'init', [$this, 'on_init'], 5000 );
    }
    public function on_init() {
        
        // Фильтры, потому что почему бы и нет!
        $this->args      = apply_filters( 'my_plugin_template_type_args', [ 'public' => true ] );
        $this->folder    = apply_filters( 'my_plugin_template_directory', __DIR__ . '/templates/' );
        $this->templates = apply_filters( 'my_plugin_template_file_list', $this->templates );
        // Устанавливаем типы записей
        $this->types     = get_post_types( $this->args );
        
        // Мы не используем шаблоны страниц для вложений
        unset( $this->types['attachment'] );
        
        // Добавляем пользовательские файлы в список шаблонов
        add_filter( 'theme_templates', [$this,'add_plugin_templates'], 1000, 4 );
        
        // Если страница — один из типов
        if( isset( $this->types['page'] ) )
            add_filter( 'page_template', [$this,'set_plugin_page_template'], 1000, 3 );
        
        // И обрабатываем другие типы записей
        add_filter( 'single_template', [$this,'set_plugin_type_template'], 1000, 3 );   
    }
    public function add_plugin_templates( $post_templates, $obj, $post, $post_type ) {
        
        if( !isset( $this->types[$post_type] ) )
            return $post_templates;
        
        foreach( $this->templates as $file => $name )
            $post_templates[$file] = $name;
        
        return $post_templates;
    }
    private function is_plugin_template( $file ) {
        return (bool) isset( $this->templates[$file] ) && file_exists( $this->folder . $file );
    }
    public function set_plugin_page_template( $template, $type, $templates ) {
        
        if( !isset( $templates[0] ) )
            return $template;
        
        if( $this->is_plugin_template( $templates[0] ) )
            return $this->folder . $templates[0];
        
        return $template;
    }
    public function set_plugin_type_template( $template, $type, $templates ) {
        
        if( !isset( $templates[0] ) || 'single' !== $type )
            return $template;
        
        if( $this->is_plugin_template( $templates[0] ) )
            return $this->folder . $templates[0];
        
        return $template;
    }
    // Простая функция для отладки / проверки значений
    private function pre( $s ) {
        printf( '<pre>%s</pre>', print_r( $s, true ) );
    }
}
new Plugin_Templates;

Я постарался не быть слишком абстрактным и сохранить логику достаточно простой. Если возникнут проблемы — оставьте комментарий.

3 нояб. 2022 г. 16:48:26
2
-4
<?php load_template( $_template_file, $require_once ) ?>

Это из первых результатов поиска Google по запросу "load template from plugin". Пожалуйста, попытайтесь найти ответы самостоятельно, прежде чем спрашивать здесь.

9 февр. 2017 г. 15:39:28
Комментарии

Если вы не хотите, чтобы тема или дочерняя тема могли переопределять шаблон плагина, просто используйте require($template)

mrben522 mrben522
9 февр. 2017 г. 15:41:47

Конечно, я видел это в Google. Думаю, вы не поняли мой вопрос. Я хочу, чтобы шаблон отображался в выпадающем списке "Атрибуты страницы", чтобы пользователь мог выбрать его при создании/редактировании страницы.

smartcat smartcat
9 февр. 2017 г. 15:45:03