Добавление пользовательского шаблона страницы программным путем

29 мар. 2011 г., 14:14:31
Просмотры: 24.6K
Голосов: 7

Я пытаюсь добавить шаблон страницы из плагина, и мой файл шаблона находится в папке этого плагина. Возможно ли это? Вот мой код:

global $user_ID;
    $new_post = array(
        'post_title' => 'Тестовая страница шаблона',
        'post_content' => 'Некоторый текст',
        'post_status' => 'publish',
        'post_date' => date('Y-m-d H:i:s'),
        'post_author' => $user_ID,
        'post_type' => 'page',
        'post_category' => array(0)
    );
    $post_id = wp_insert_post($new_post);
    if (!$post_id) {
        wp_die('Ошибка создания страницы шаблона');
    } else {
        update_post_meta($post_id, '_wp_page_template', 'tp-file.php');
    }

tp-file.php - это мой пользовательский шаблон страницы. Когда я помещаю этот файл в папку my-theme, он работает нормально, но я хочу сделать это с файлом из папки плагина, чтобы пользователям не приходилось копировать этот файл из папки плагина в папку шаблона. Возможно ли это? Есть какие-нибудь идеи?

4
Комментарии

http://www.unfocus.com/2010/08/10/including-page-templates-from-a-wordpress-plugin/ Кажется, решает эту проблему. Я не очень хорошо с этим знаком, поэтому не могу сказать, работает это или нет.

Rev. Voodoo Rev. Voodoo
29 мар. 2011 г. 14:45:02

Спасибо @Rev.Voodoo, посмотрю.

user1147 user1147
29 мар. 2011 г. 15:11:20

@Rev.Voodoo нет, это не помогло

user1147 user1147
30 мар. 2011 г. 00:54:26

что содержится в файле tp-file.php?

User User
1 янв. 2012 г. 11:27:46
Все ответы на вопрос 3
15
13

Статья по ссылке движется в правильном направлении, но я упрощу её для вас.. ;)

add_filter( 'page_template', 'catch_plugin_template' );

function catch_plugin_template( $template ) {
    if( 'tp-file.php' == basename( $template ) )
        $template = WP_PLUGIN_DIR . '/yourpluginname/tp-file.php';
    return $template;
}

Этот фильтр проверяет, установлен ли ваш специальный шаблон страницы для текущей страницы, и если да, обновляет путь, указывая на шаблон вашего плагина.

Просто убедитесь, что путь указан верно, иначе вы увидите ошибки подключения... :)

Дополнение #1

Первая проблема заключается в том, что WordPress проверяет любой шаблон, установленный как шаблон страницы, то есть он проверяет, находится ли файл в папке темы и является ли он валидным шаблоном. Если нет, он пропускает его и подключает более общий шаблон, например page.php...

Однако это не меняет того факта, что метаполе всё ещё хранит значение вашего кастомного шаблона, и также is_page_template( 'tp-file.php' ) будет корректно возвращать true, если использовать его вместо моего предыдущего условия, например..

// Фильтр шаблона страницы
add_filter('page_template', 'catch_plugin_template');

// Колбэк фильтра шаблона страницы
function catch_plugin_template($template) {
    // Если tp-file.php установлен как шаблон
    if( is_page_template('tp-file.php') )
        // Обновляем путь (должен быть путь, используем WP_PLUGIN_DIR, а не WP_PLUGIN_URL) 
        $template = WP_PLUGIN_DIR . '/tp-test/tp-file.php';
    // Возвращаем
    return $template;
}

ПРИМЕЧАНИЕ: Я изменил код, чтобы использовать WP_PLUGIN_DIR, так как константа WP_PLUGIN_URL не подходит для путей... (подключение файлов требует пути, а не URL).

Одна проблема, которую нельзя исправить, заключается в том, что при просмотре страницы из админки во время её редактирования, шаблон не будет отображаться как активный, и сохранение изменений может изменить активный шаблон. С этим мало что можно сделать, так как выпадающий список шаблонов страниц генерируется функцией, которая сканирует файлы темы, и нет хуков, которые позволили бы нам расширить этот список шаблонами из плагина.

Лично я бы предложил в качестве обходного решения сохранять дополнительное метаполе для каждой страницы, созданной с помощью вашего специального плагина, затем добавить хук на save_post или wp_insert_post_data и проверять, существует ли это метаполе. Если существует, также проверять, установлен ли шаблон страницы в tp-file.php, и если нет, обновлять его до tp-file.php. Дополнительное метаполе будет просто флагом, указывающим, какие страницы должны использовать шаблон вашего плагина.

Вот ваш плагин в самой базовой форме (да, я тестировал)... :)

<?php
/*
  Plugin Name: TP Test Plugin
  Plugin URI: 
  Description: TP Test Plugin
  Version: 1.0.0
  Author: 
  Author URI: 
*/

global $wp_version;

if( version_compare( $wp_version, "2.9", "<" ) )
    exit( 'Для этого плагина требуется WordPress 2.9 или новее. <a href="http://codex.wordpress.org/Upgrading_WordPress">Пожалуйста, обновитесь!</a>' );

// Добавляем колбэк в меню админки
add_action('admin_menu', 'create_tp_menu');

// Колбэк для добавления пунктов меню
function create_tp_menu() {
    add_management_page('TP Test', 'TP Test', 'manage_options', 'tp-teste', 'wp_tp_test_fnc' );
}

function wp_tp_test_fnc() {

    //include('tp-form-file.php');

    if( !empty( $_POST['tp_name'] ) ) {
        $tp_name = $_POST['tp_name'];

        global $user_ID;
        $new_post = array(
            'post_title' => $tp_name,
            'post_content' => 'Некоторый текст',
            'post_status' => 'publish',
            'post_date' => date('Y-m-d H:i:s'),
            'post_author' => $user_ID,
            'post_type' => 'page',
        );
        $post_id = wp_insert_post($new_post);

        if( !$post_id )
            wp_die('Ошибка при создании страницы шаблона');
        else
            update_post_meta( $post_id, '_wp_page_template', 'tp-file.php' );
        /*
        $pt = get_page_templates();

        $pt['TP file test'] = WP_PLUGIN_URL . '/tp-test/tp-file.php';

        echo "<pre>";
        print_r($pt);
        echo "</pre>";
        */
    }   
    ?>
    <fieldset style="margin: 50px 100px;background-color: #cccccc;padding: 30px;border: 1px solid #ccc">
         <legend style="background-color: #ccccff;padding: 20px;font-weight: bold;font-size: 18px">Создать страницу шаблона</legend>
         <form name="frm_main" action="" method="POSt">
              <input class="text" type="text" name="tp_name" size="50" />
              <br />
              <input class="button" type="submit" value="Создать страницу шаблона" name="btn_submit" />
         </form>
    </fieldset>
    <?php

}


// Фильтр шаблона страницы
add_filter('page_template', 'catch_plugin_template');

// Колбэк фильтра шаблона страницы
function catch_plugin_template($template) {
    // Если tp-file.php установлен как шаблон
    if( is_page_template('tp-file.php') )
        // Обновляем путь (должен быть путь, используем WP_PLUGIN_DIR, а не WP_PLUGIN_URL) 
        $template = WP_PLUGIN_DIR . '/tp-test/tp-file.php';
    // Возвращаем
    return $template;
}

Надеюсь, это поможет прояснить ситуацию.. :)

30 мар. 2011 г. 02:21:03
Комментарии

Спасибо @t31os, я попробовал это, но это не сработало, затем я нашел это http://adambrown.info/p/wp_hooks/hook/page_template, что устарело, есть другие идеи?

user1147 user1147
30 мар. 2011 г. 02:31:51

Я также попробовал что-то вроде этого, но это не сработало : $pt = get_page_templates(); $pt['TP testing'] = WP_PLUGIN_URL . '/tp-test/tp-file.php';

user1147 user1147
30 мар. 2011 г. 02:38:15

У меня это работает прекрасно... Мне нужно больше деталей, чем просто "это не сработало".

t31os t31os
30 мар. 2011 г. 02:46:51

Похоже, что шаблонные файлы не включены в подпапке. Я обнаружил это в функции get_page_templates в файле theme.php. Есть другие идеи?

user1147 user1147
30 мар. 2011 г. 02:48:09

Это не имеет значения, предоставленный мной код будет работать нормально, при условии что путь указан правильно и у запрашиваемой страницы установлено _wp_page_template в значение tp-file.php... Я только что перепроверил снова, чтобы убедиться, и снова подтвердил, что код работает (мне нужно увидеть больше вашего кода, если вы хотите, чтобы я помог разобраться, почему он не работает в вашей настройке).

t31os t31os
30 мар. 2011 г. 02:53:31

Спасибо за ваше время, мой код не менялся, единственное - я добавил ваш код в мой основной файл плагина, посмотрите здесь: http://pastebin.com/sNR9s0sP

user1147 user1147
30 мар. 2011 г. 03:05:20

Я также проверил таблицу wp_postmeta, всё выглядит нормально

user1147 user1147
30 мар. 2011 г. 03:07:58

Хорошо, но что происходит, когда вы загружаете страницу, у которой _wp_page_template установлен в tp-file.php? Вы видите ошибку включения, пустую страницу или что-то ещё? Помогите мне помочь вам... ;)

t31os t31os
30 мар. 2011 г. 03:08:39

Я вижу "Какой-то текст", как на обычной странице, и если я перехожу в админку, то вижу, что шаблон страницы установлен на стандартный, и моего файла шаблона нет в списке

user1147 user1147
30 мар. 2011 г. 03:10:34

Я собираюсь лечь спать в ближайшие минуты, но завтра я уточню этот вопрос для вас. Пока метаполе _wp_page_template остается правильно установленным, всё должно работать, независимо от того, что оно не отображается в админке (что ожидаемо — объясню в обновлении ответа завтра).

t31os t31os
30 мар. 2011 г. 03:17:41

Ок, спасибо @t31os за помощь

user1147 user1147
30 мар. 2011 г. 03:19:33

Пожалуйста... и я только что обновил свой ответ.. ;)

t31os t31os
30 мар. 2011 г. 12:56:21

Хм, это странно, код не работает, когда форма в отдельном файле, но если она вместе, то всё работает.

user1147 user1147
30 мар. 2011 г. 13:49:03

Попробуй указать action в твоей форме, например action="<?php admin_url( '/?page=tp-teste' ) ?>", чтобы убедиться, что она отправляется на страницу твоего плагина корректно.

t31os t31os
30 мар. 2011 г. 13:54:56

Ааааа, боже, это и было проблемой. Спасибо @t31os за уделенное время.

user1147 user1147
30 мар. 2011 г. 14:09:51
Показать остальные 10 комментариев
2

Фильтр page_template теперь считается устаревшим. (http://adambrown.info/p/wp_hooks/hook/page_template)

Вместо него рекомендуется использовать single_template (или archive_template для архивных шаблонов).

На основе ответа @t31os:

// Фильтр шаблона страницы
add_filter('single_template', 'catch_plugin_template');

// Функция обратного вызова для фильтра шаблона страницы
function catch_plugin_template($template) {
    // Если установлен шаблон tp-file.php
    if( is_page_template('tp-file.php') )
        // Обновляем путь (должен быть путь, используйте WP_PLUGIN_DIR, а не WP_PLUGIN_URL)
        $template = WP_PLUGIN_DIR . '/tp-test/tp-file.php';
    // Возвращаем
    return $template;
}
23 июн. 2016 г. 17:20:10
Комментарии

если фильтр single_template не сработал, можно использовать этот фильтр: add_filter('template_include', 'catch_plugin_template');

взято отсюда: https://www.pradipdebnath.com/2019/08/17/how-to-add-page-template-from-plugin-in-wordpress/

ewroman ewroman
18 апр. 2020 г. 07:59:47

Не уверен, что он устарел, просто изменился с версии 4.7. https://developer.wordpress.org/reference/hooks/type_template/.The аргумент пуст, если тема(ы) не предоставляют шаблон, а не если страница выбрала (сохранила) его в базе данных из выпадающего списка.

Jonas Lundman Jonas Lundman
4 дек. 2021 г. 10:49:31
0

Одна проблема, и это не то, что можно исправить, заключается в том, что при просмотре страницы из админки, во время её редактирования, шаблон не будет отображаться как активный, и сохранение изменений может, конечно же, изменить активный шаблон. Здесь мало что можно сделать - выпадающий список шаблонов страниц генерируется функцией, которая сканирует файлы темы, и нет хуков, которые позволили бы нам расширить этот список шаблонами из плагина.

На самом деле я нашёл хук в другой теме, который делает именно это:

WordPress: Можно ли программно создавать шаблоны страниц?

Для удобства вставляю код здесь:

CONST CUSTOM_PAGE_TEMPLATES = array(
  array('slug' => 'home', 'label' => 'Главная'),
  array('slug' => 'content-page', 'label' => 'Страница контента'),
  array('slug' => 'ordering', 'label' => 'Оформление заказа'),
  array('slug' => 'reviews', 'label' => 'Отзывы')
);

/**
 * Добавляет шаблоны страниц без файлов в выпадающий список шаблонов
 */
add_filter('theme_page_templates', function($page_templates, $wp_theme, $post) {
  foreach(CUSTOM_PAGE_TEMPLATES as $template) {
    // Добавляем, если ещё не существует
    if (!isset($page_templates[$template['slug']])) {
      $page_templates[$template['slug']] = $template['label'];
    }
  }
  return $page_templates;
}, PHP_INT_MAX, 3);

Надеюсь, это кому-то поможет.

20 апр. 2021 г. 10:06:53