wordpress WP - 使用插件目录中的文件作为自定义页面模板?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4647604/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 18:42:04  来源:igfitidea点击:

WP - Use file in plugin directory as custom Page Template?

wordpress

提问by Jared

Is it possible for a file in the plugin directory to be used as a custom Page Template?

插件目录中的文件是否可以用作自定义页面模板?

Also, how do you make a plugin create a page?

另外,你如何让插件创建一个页面?

I'm developing a plugin for a client based on a theme, he wants this plugin to make sales pages while being able to use his theme on the homepage. This is a product that I'm making for him to market so it needs to be automated all through the plugin.

我正在为一个基于主题的客户开发一个插件,他希望这个插件能够制作销售页面,同时能够在主页上使用他的主题。这是我为他制作的产品,因此需要通过插件实现自动化。

Is this possible?

这可能吗?

EDIT

编辑

I have the activation/deactivation hooks in my plugins main file, and it's not working. Here's the code:

我的插件主文件中有激活/停用挂钩,但它不起作用。这是代码:

$filename = __FILE__;

register_activation_hook($filename, 'superActivation');
register_deactivation_hook($filename, 'superDeactivation');

global $myFile; global $fh; global $stringData; global $filename;

$myFile = "testFile.txt";
$stringData = "Testing\n";
$fh = fopen($myFile, 'w') or die("can't open file");

function superActivation() {
    global $myFile; global $fh; global $stringData; global $filename;
    fwrite($fh, $stringData);
    fclose($fh);
}

function superDeactivation() {
    $myFile = "testFile.txt";
    unlink($myFile);
}

回答by David

You can do this with the template_redirect hook. Here's my code to manually replace the template for a custom post type with one in the theme if there isn't one in the template folder. Put this in your plugin file and then put a folder underneath your plugin called themefiles with your default theme files.

您可以使用 template_redirect 钩子来做到这一点。这是我的代码,如果模板文件夹中没有模板,则将自定义帖子类型的模板手动替换为主题中的模板。将它放在您的插件文件中,然后在您的插件下放置一个名为 themefiles 的文件夹,其中包含您的默认主题文件。

//Template fallback
add_action("template_redirect", 'my_theme_redirect');

function my_theme_redirect() {
    global $wp;
    $plugindir = dirname( __FILE__ );

    //A Specific Custom Post Type
    if ($wp->query_vars["post_type"] == 'product') {
        $templatefilename = 'single-product.php';
        if (file_exists(TEMPLATEPATH . '/' . $templatefilename)) {
            $return_template = TEMPLATEPATH . '/' . $templatefilename;
        } else {
            $return_template = $plugindir . '/themefiles/' . $templatefilename;
        }
        do_theme_redirect($return_template);

    //A Custom Taxonomy Page
    } elseif ($wp->query_vars["taxonomy"] == 'product_categories') {
        $templatefilename = 'taxonomy-product_categories.php';
        if (file_exists(TEMPLATEPATH . '/' . $templatefilename)) {
            $return_template = TEMPLATEPATH . '/' . $templatefilename;
        } else {
            $return_template = $plugindir . '/themefiles/' . $templatefilename;
        }
        do_theme_redirect($return_template);

    //A Simple Page
    } elseif ($wp->query_vars["pagename"] == 'somepagename') {
        $templatefilename = 'page-somepagename.php';
        if (file_exists(TEMPLATEPATH . '/' . $templatefilename)) {
            $return_template = TEMPLATEPATH . '/' . $templatefilename;
        } else {
            $return_template = $plugindir . '/themefiles/' . $templatefilename;
        }
        do_theme_redirect($return_template);
    }
}

function do_theme_redirect($url) {
    global $post, $wp_query;
    if (have_posts()) {
        include($url);
        die();
    } else {
        $wp_query->is_404 = true;
    }
}

回答by Nolan Dempster

the code david posted above almost works for me. but it seems to blanket over all posts and pages for me. This code below works great for adding a template to a single post type that is created by my main plugin file

上面发布的代码大卫几乎对我有用。但它似乎覆盖了我所有的帖子和页面。下面的代码非常适合将模板添加到由我的主插件文件创建的单个帖子类型

function get_book_post_type_template($single_template) {
 global $post;

 if ($post->post_type == 'books') {
      $single_template = dirname( __FILE__ ) . '/themefiles/single-books.php';
 }
 return $single_template;
}

add_filter( "single_template", "get_book_post_type_template" ) ;

but I'm having trouble getting it to work with a custom page templates that don't have a post_type or has a post_type = page for instance lets say the custom page is an auxiliary member login page to see my custom posts. in my case this file is called myaccount.php and i've included it in a subfolder within my plugin folder named themefiles.

但我无法让它与没有 post_type 或具有 post_type = 页面的自定义页面模板一起使用,例如可以说自定义页面是一个辅助成员登录页面,用于查看我的自定义帖子。在我的例子中,这个文件叫做 myaccount.php,我已经将它包含在我的插件文件夹中名为 themefiles 的子文件夹中。

//Add Page and Post Template Files to Current Theme 
add_action("template_redirect", 'my_account_redirect');

function my_account_redirect() {
    global $wp;

    //Set myAccount Custom Page Template 
    if (isset($wp->query_vars['pagename'] ) == "myaccount") {
        $templatefilename = 'myAccount.php';
        if (file_exists(dirname( __FILE__ ) . '/themefiles/' . $templatefilename)) {
            $return_template = dirname( __FILE__ ) . '/themefiles/' . $templatefilename;
        }
        do_account_redirect($return_template);
    } 
} 

//Finishing setting templates 
function do_account_redirect($url) {
    global $post, $wp_query;

    if (have_posts()) {
        include($url);
        die();
    } else {
        $wp_query->is_404 = true;
    }
}

when i do the above code the myaccount template shows up on all pages except for home which i believe is because it is set to a blogroll instead of a static page

当我执行上述代码时,myaccount 模板会显示在除 home 之外的所有页面上,我认为这是因为它设置为 blogroll 而不是静态页面

回答by Harri Bell-Thomas

You CANadd page templates from a plugin very easily by manipulating the page cache.

CAN从一个插件很容易通过操纵页面缓存添加页面模板。

To customise, simply edit the following code block within the __construct method;

要自定义,只需在 __construct 方法中编辑以下代码块;

   $this->templates = array(
       'goodtobebad-template.php'     => 'It\'s Good to Be Bad',
   );

This is designed for a plugin (the template files are searched for in the root directory of the plugin). This can be changed if desired - check out my full tutorial http://www.wpexplorer.com/wordpress-page-templates-plugin/for greater detail on this solution. These files are also in exactly the same format as if they were to be included directly in a theme.

这是为插件设计的(在插件的根目录中搜索模板文件)。如果需要,可以更改此设置 - 查看我的完整教程http://www.wpexplorer.com/wordpress-page-templates-plugin/以获取有关此解决方案的更多详细信息。这些文件的格式也与直接包含在主题中的格式完全相同。

Full code;

完整代码;

class PageTemplater {

    /**
     * A Unique Identifier
     */
     protected $plugin_slug;

    /**
     * A reference to an instance of this class.
     */
    private static $instance;

    /**
     * The array of templates that this plugin tracks.
     */
    protected $templates;


    /**
     * Returns an instance of this class. 
     */
    public static function get_instance() {

            if( null == self::$instance ) {
                    self::$instance = new PageTemplater();
            } 

            return self::$instance;

    } 

    /**
     * Initializes the plugin by setting filters and administration functions.
     */
    private function __construct() {

            $this->templates = array();


            // Add a filter to the attributes metabox to inject template into the cache.
            add_filter(
                'page_attributes_dropdown_pages_args',
                 array( $this, 'register_project_templates' ) 
            );


            // Add a filter to the save post to inject out template into the page cache
            add_filter(
                'wp_insert_post_data', 
                array( $this, 'register_project_templates' ) 
            );


            // Add a filter to the template include to determine if the page has our 
            // template assigned and return it's path
            add_filter(
                'template_include', 
                array( $this, 'view_project_template') 
            );


            // Add your templates to this array.
            $this->templates = array(
                    'goodtobebad-template.php'     => 'It\'s Good to Be Bad',
            );

    } 


    /**
     * Adds our template to the pages cache in order to trick WordPress
     * into thinking the template file exists where it doens't really exist.
     *
     */

    public function register_project_templates( $atts ) {

            // Create the key used for the themes cache
            $cache_key = 'page_templates-' . md5( get_theme_root() . '/' . get_stylesheet() );

            // Retrieve the cache list. 
            // If it doesn't exist, or it's empty prepare an array
            $templates = wp_get_theme()->get_page_templates();
            if ( empty( $templates ) ) {
                    $templates = array();
            } 

            // New cache, therefore remove the old one
            wp_cache_delete( $cache_key , 'themes');

            // Now add our template to the list of templates by merging our templates
            // with the existing templates array from the cache.
            $templates = array_merge( $templates, $this->templates );

            // Add the modified cache to allow WordPress to pick it up for listing
            // available templates
            wp_cache_add( $cache_key, $templates, 'themes', 1800 );

            return $atts;

    } 

    /**
     * Checks if the template is assigned to the page
     */
    public function view_project_template( $template ) {

            global $post;

            if (!isset($this->templates[get_post_meta( 
                $post->ID, '_wp_page_template', true 
            )] ) ) {

                    return $template;

            } 

            $file = plugin_dir_path(__FILE__). get_post_meta( 
                $post->ID, '_wp_page_template', true 
            );

            // Just to be safe, we check if the file exist first
            if( file_exists( $file ) ) {
                    return $file;
            } 
            else { echo $file; }

            return $template;

    } 


} 

add_action( 'plugins_loaded', array( 'PageTemplater', 'get_instance' ) );

Check out my tutorial on this for more info.

查看我的教程以获取更多信息。

http://www.wpexplorer.com/wordpress-page-templates-plugin/

http://www.wpexplorer.com/wordpress-page-templates-plugin/

I hope this helps you in what you want to do :)

我希望这可以帮助您完成您想做的事情:)

回答by Matt

I cannot reply to user1912899, but their recommendation seems to be the most elegant solution. To use a custom template to override single-post.php, I've implemented the following code. This will work for any custom single-****.php file you add to your plugin. If it doesn't exist, it just falls back to what WordPress normally uses.

我无法回复 user1912899,但他们的建议似乎是最优雅的解决方案。为了使用自定义模板来覆盖 single-post.php,我实现了以下代码。这适用于您添加到插件的任何自定义 single-****.php 文件。如果它不存在,它只会退回到 WordPress 通常使用的内容。

add_action('template_include', 'my_template_include');
function my_template_include($template) {

    $file = dirname( __FILE__ ).'/theme/single-'.get_post_type().'.php';
    if(file_exists($file)) {
        $template = $file;
    }

    return $template;

}