фильтр template_include не рендерит пользовательский шаблон

Вопрос или проблема

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

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

Вот мой код:

api.php

   class Api{

    public static $logger = null;

    function Api() {
        add_shortcode('my_shortcode', array(&$this, 'my_shortcode_function'));
    }

    function my_shortcode_function($atts,$content = null)   
    {
        add_filter( 'template_include', 'custom_view');         
    }

    function custom_view()
    {
        $template = plugin_dir_path( __FILE__ ) . 'custom-page.php';

        return $template;

    }
}

    add_action('init', 'apiInit', 10);
    function apiInit() {

    global $api; 

  if (class_exists('Api')){
    $api = new Api();
  }
    }

А вот и мой custom-page.php (в котором я на 100% уверен, что он в правильном пути / директории, на который я указываю в коде)

   <?php
   /**
    * Шаблон ответа
    * Файл: custom-page.php
    *
    */
   echo 'Я здесь!';
  <?

Пытался отладить каждую функцию, она проходит через my_shortcode_function(), но не проходит через функцию custom_view.

Ура!

Фильтр template_include срабатывает гораздо раньше и используется для загрузки основного шаблона запросов.

Ваш контент будет вызываться из the_content(), $GLOBALS['post']->post_content или из того, что вы используете для его отображения. Суть в том, что вы не можете использовать фильтр, так как он не сработает. Попробуйте просто использовать что-то вроде require/include.

Поскольку template_include срабатывает очень рано, даже до add_shorcode. Вот моё решение проблемы.

class Api{

public static $logger = null;

function Api() {
    add_filter('template_include', array(&$this, 'custom_view'));
}

function custom_view($template){
    global $post;

    if(!is_admin() && str_contains($post->post_content,'[my_shortcode]')){
    $template = plugin_dir_path( __FILE__ ) . 'custom-page.php';

    return $template;

    }else{
        return $template;
    }
}}

Ответ или решение

Решение проблемы с неработающим фильтром template_include для пользовательского шаблона

При разработке плагина для WordPress, у вас возникла проблема с фильтром template_include, который не позволяет рендерить пользовательский шаблон. Давайте разберем вашу ситуацию и предложим оптимальное решение.

Изначальная проблема

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

Анализ исходного кода

Ваш оригинальный код добавляет фильтр в функцию my_shortcode_function, которая вызывается тогда, когда WordPress рендерит контент страницы. Однако вызов фильтра template_include должен происходить прежде, чем произойдет рендеринг контента. Таким образом, фильтр никогда не сработает, так как его добавление происходит слишком поздно в жизненном цикле WordPress.

Решение

В вашем случае правильным подходом будет добавление фильтра template_include в конструктор класса Api, что позволит ловить стандартный процесс загрузки шаблонов до обращения к контенту. Важно также учитывать использование глобальной переменной $post, чтобы убедиться, что шорткод действительно присутствует в контенте. Это позволит избежать ненужной обработки страниц, где шорткод отсутствует.

Вот исправленный код:

class Api {

    public static $logger = null;

    function __construct() {
        // Добавляем фильтр template_include в конструктор класса
        add_filter('template_include', array($this, 'custom_view'));
    }

    function custom_view($template) {
        global $post;

        // Проверяем, что не в админке и шорткод присутствует в контенте поста
        if (!is_admin() && isset($post->post_content) && str_contains($post->post_content, '[my_shortcode]')) {
            $template = plugin_dir_path(__FILE__) . 'custom-page.php';
            return $template;
        } else {
            return $template;
        }
    }
}

// Инициализируем класс Api
add_action('init', 'apiInit', 10);
function apiInit() {
    global $api; 

    if (class_exists('Api')) {
        $api = new Api();
    }
}

Объяснение изменений

  1. Перенос добавления фильтра: Фильтр template_include теперь добавляется в конструктор класса Api, что гарантирует выполнение этого кода до того, как WordPress начнет рендеринг страницы.

  2. Проверка контента: В функции custom_view добавлена проверка на наличие шорткода в контенте поста, что позволяет избежать изменения шаблонов для страниц, которые не используют шорткод.

  3. Единообразие кода: Я исправил инициализацию конструктора с function Api() на function __construct(), что является стандартом в PHP для современных версий.

Заключение

Данное решение должно эффективно решить вашу проблему с рендерингом пользовательского шаблона через шорткод в WordPress. Убедитесь, что ваша структура каталогов подходит для загружаемого шаблона и протестируйте функциональность на различных страницах, чтобы убедиться в ее универсальности.

Если у вас появятся дальнейшие вопросы или понадобится обсуждение новых функций, не стесняйтесь обращаться за помощью!

Оцените материал
Добавить комментарий

Капча загружается...