如何在不修改主题的情况下控制自定义帖子类型的输出?

时间:2012-12-07 作者:Andy Adams

我有一个自定义的帖子类型“properties”,我想控制它的HTML输出。为了简单起见,让我们将重点放在archive 看法

作为一个基本示例,下面是archive.php 文件:

<?php while ( have_posts() ) : the_post(); ?>
    <h2><?php the_title(); ?></h2>
    <div><?php the_content(); ?></div>
<?php endwhile; ?>
我希望能够使用自定义的“属性”HTML修改循环的输出without adding a new template or using a shortcode - 基本上,没有用户干预。说清楚点,我想更换<h2><div> 在上面的示例中,之前/之后没有任何内容。

Note: 以上只是一个例子。我想控制循环输出,而不管主题是什么。

现在,我正在使用输出缓冲从loop_startloop_end 并将其替换为我自己的插件,但这可能会与其他插件产生冲突。

有没有公认的/更好的方法来做到这一点?

4 个回复
最合适的回答,由SO网友:kaiser 整理而成

有两个经常被遗忘的动作参考数组:loop_start/_end().

只要打开输出缓冲,就可以开始了。

add_action( \'loop_start\', \'wpse75307_plugin_loop\' );
add_action( \'loop_end\', \'wpse75307_plugin_loop\' );
/**
 * Callback function triggered during:
 * + \'loop_start\'/`have_posts()` after the last post gets rendered
 * + \'loop_end\'/`the_post()` before the 1st post gets rendered
 * @param  object \\WP_Query Passed by reference
 * @return 
 */
function wpse75307_plugin_loop( &$obj )
{
    # if ( is_main_query() )
    # DO STUFF ... OR DONT
    global $post;

    // Start output buffering at the beginning of the loop and abort
    if ( \'loop_start\' === current_filter() )
        return ob_start();

    // At the end of the loop, we end the buffering and save into a var
    # if ( is_main_query() )
    # DO STUFF ... OR DONT
    $loop_content = ob_get_flush();

    // You can do something with $loop_content...
    // Add your own loop, or...
    // Whatever you can imagine
}
注意:我不会这样做,但正如你所说,你想要的正是那种级别的覆盖,给你。

SO网友:bueltge

您可以通过钩子更改循环,如cpt“my\\u post\\u type”中所示

// $this? - example was used in class-structures
// add custom post type to wp loop
add_filter( \'pre_get_posts\', array( $this, \'add_to_query\') );

// ads to query
function add_to_query( $query ) {

    if ( is_admin() || is_preview() )
        return;

    if ( ! isset( $query -> query_vars[\'suppress_filters\'] ) )
        $query -> query_vars[\'suppress_filters\'] = FALSE;

    // conditional tags for restrictions
    if ( is_home() || is_front_page() && ( FALSE == $query -> query_vars[\'suppress_filters\'] ) ) 
        $query->set( \'post_type\', array( \'post\', \'my_post_type\' ) );

    return $query;
}

SO网友:brasofilo

如果记得很清楚的话,我从这里得到了这个技巧:Use template_include with custom post types.

我们使用的插件将生成一个;“虚拟模板”;对于给定的职位类型。过滤器template_include 将呈现位于插件文件夹中的模板文件。

您必须优化函数custom_template 和模板文件,以满足您的需要。希望这有帮助;)

插件文件adjust the post_type name in the class instantiation

<?php
! defined( \'ABSPATH\' ) AND exit;
/*
Plugin Name: Virtual Template for CPT
Plugin URI: https://wordpress.stackexchange.com/q/75307/12615
Description: Use the plugin\'s template file to render an outsider loop.
Author: brasofilo
Author URI: https://wordpress.stackexchange.com/users/12615/brasofilo
Version: 2012.12.11
License: GPLv2
*/

$virtual_template = new VirtualTemplateForCPT_class( \'movies\' );

class VirtualTemplateForCPT_class
{   
    private $pt;
    private $url;
    private $path;

    /**
     * Construct 
     *
     * @return void
     **/
    public function __construct( $pt )
    {       
        $this->pt = $pt;
        $this->url = plugins_url( \'\', __FILE__ );
        $this->path = plugin_dir_path( __FILE__ );
        add_action( \'init\', array( $this, \'init_all\' ) );
    }
        
    
    /**
     * Dispatch general hooks
     *
     * @return void
     **/
    public function init_all() 
    {
        add_action( \'wp_enqueue_scripts\',   array( $this, \'frontend_enqueue\' ) );
        add_filter( \'body_class\',           array( $this, \'add_body_class\' ) );
        add_filter( \'template_include\',     array( $this, \'custom_template\' ) );
    }

    /**
     * Use for custom frontend enqueues of scripts and styles
     * http://codex.wordpress.org/Plugin_API/Action_Reference/wp_enqueue_scripts
     *
     * @return void
     **/
    public function frontend_enqueue() 
    {
        global $post;
        if( $this->pt != get_post_type( $post->ID ) )
            return;         
    }
    
    /**
     * Add custom class to body tag
     * http://codex.wordpress.org/Function_Reference/body_class
     *
     * @param array $classes
     * @return array
     **/
    public function add_body_class( $classes ) 
    {
        global $post;
        if( $this->pt != get_post_type( $post->ID ) )
            return $classes;
            
        $classes[] = $this->pt . \'-body-class\';
        return $classes;
    }
       
    /**
     * Use the plugin template file to display the CPT
     * http://codex.wordpress.org/Conditional_Tags
     *
     * @param string $template
     * @return string
     **/
    public function custom_template( $template ) 
    {
        $post_types = array( $this->pt );
        $theme = wp_get_theme();
    
        if ( is_post_type_archive( $post_types ) )
            $template = $this->path . \'/single-virtual-cpt.php\';
        
        if ( is_singular( $post_types ) )
            $template = $this->path . \'/single-virtual-cpt.php\';
        
        return $template;
    }
    
}
模板文件single-virtual-cpt.php
将插件文件放在同一文件夹中

<?php
/**
 * A custom -not from the theme- template
 *
 * @package WordPress
 * @subpackage Virtual_Template
 */

get_header(); 

while ( have_posts() ) : the_post(); $theID = $post->ID; 
    _e(\'This is a virtual template for the post:<br />\');
    the_title();
endwhile; 
get_footer(); 

?>
</body>
</html>
结果virtual template in frontend
单击放大⤴

SO网友:Dave Hilditch

我也一直在尝试解决这个问题——我有一个带有自定义帖子类型的插件,这些自定义帖子类型需要自定义存档,但创建特定的模板文件意味着它不能适用于所有主题。

我能想到的上面没有提到的最接近的替代方法是读取存档/索引。php文件上的插件激活(和主题更改)并复制存档。php文件到您的插件文件夹,并更改相关名称,以特定于您的自定义帖子类型。

然后,让插件自动修改自定义模板文件,以插入自己的循环代码。

<?php while (have_posts()) : the_post(); ?>     
    <?php if(is_search()): ?>
        <?php get_template_part( \'includes/loop\' , \'search\'); ?>
    <?php else: ?>
        <?php get_template_part( \'includes/loop\' , \'index\'); ?>
    <?php endif; ?>
<?php endwhile; ?>
例如,在上面的索引小片段中。php文件,扫描while(have\\u posts()…)并用自定义循环html代码替换中间的所有内容。

我没有尝试过这种方法,这只是另一种潜在的解决方案,如果其他人使用过这种方法,我将不胜感激。

结束

相关推荐

如何将此循环重写为新的WP_QUERY-LOOP?

如何重写if (have_posts()) : ... while (have_posts()) : the_post(); 使用以下样式将Wordpress循环设置为新的\\u查询样式循环<?php $the_query = new WP_Query();? (如所示http://codex.wordpress.org/Class_Reference/WP_Query )下面的当前循环交替显示帖子类,以显示一个由两个帖子宽的帖子组成的网格(请参见下图)。但我需要使用一个新的查询来重写它,以便:1)