web-dev-qa-db-ja.com

テーマを変更せずにカスタム投稿タイプの出力を制御する方法

HTML出力を制御したいカスタム投稿タイプ 'properties'があります。簡単にするために、archiveビューに注目しましょう。

基本的な例として、ループがarchive.phpファイル内でどのように見えるかを示します。

<?php while ( have_posts() ) : the_post(); ?>
    <h2><?php the_title(); ?></h2>
    <div><?php the_content(); ?></div>
<?php endwhile; ?>

私は自分のカスタム 'properties' HTMLを使って新しいテンプレートを追加したりショートコードを使わずにループの出力を変更できるようにしたいです。 。明確にするために、上記の例の<h2><div>を置き換えますが、その前後には何も入れません。

注:上記は一例です。テーマに関係なくループ出力を制御したい

現在、私はloop_startからloop_endへの出力をキャプチャするために出力バッファリングを使用していて、それを私自身のものと取り替えています、しかしこれは潜在的に他のプラグインと衝突を起こすことができます。

これを行うための承認された/より良い方法はありますか?

5
Andy Adams

忘れられがちなアクション参照配列が2つあります: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
}

注:私はこのようにはしませんが、あなたが言ったように、あなたはまさにそのレベルのオーバーライドを望んでいます。

4
kaiser

Cpt 'my_post_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;
}
0
bueltge

私もこれの解決策を見つけようとしています - 私はカスタム投稿タイプのプラグインを持っています、それらのカスタム投稿タイプはカスタムアーカイブを必要としますが特定のテンプレートファイルを作成することはそれがすべてのテーマでうまくいかないことを意味します。

私が考えることができる最も近い代替案は、プラグインの有効化(およびテーマの変更)でarchive/index.phpファイルを読み、関連する名前を変更してarchive.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; ?>

例えばindex.phpファイルの上の小さな断片で、while(have_posts()...)行と対応する行をスキャンして、その間にあるすべてをカスタムループのHTMLコードに置き換えます。

私はこれを試したことはありません、それはもう一つの潜在的な解決策であり、他の誰かがこのアプローチを使ったことがあれば私はコメントをいただければ幸いです。

0
Dave Hilditch

よく覚えていれば、私はここからこのテクニックを導き出しました: カスタム投稿タイプでtemplate_includeを使用してください

与えられた投稿タイプに対して "バーチャルテンプレート"を生成するプラグインを使います。フィルタ template_include は、プラグインフォルダにあるテンプレートファイルをレンダリングします。

あなたはあなたのニーズに合うように関数custom_templateとテンプレートファイルを改良しなければなりません。お役に立てれば ;)


プラグインファイル

クラスのインスタンス化でpost_typeの名前を調整する

<?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 
クリックすると拡大します⤴

0
brasofilo