Tạo trang lưu trữ tùy chỉnh cho loại bài đăng tùy chỉnh trong plugin


11

Tôi đang viết một plugin tạo ra một loại bài đăng tùy chỉnh có tên "my_plugin_lesson":

$args = array (
    'public' => true,
    'has_archive' => true,
    'rewrite' => array('slug' => 'lessons', 'with_front' => false)
);
register_post_type ('my_plugin_lesson', $args);

Loại bài đăng tùy chỉnh có một kho lưu trữ và URL của kho lưu trữ là:

http://example.com/lessons

Tôi muốn tùy chỉnh giao diện của kho lưu trữ này; Tôi muốn liệt kê các bài đăng theo định dạng bảng, thay vì lưu trữ bài đăng trên blog tiêu chuẩn của WordPress. Tôi hiểu rằng một mẫu lưu trữ tùy chỉnh có thể được tạo trong chủ đề bằng cách tạo archive-my_plugin_lesson.phptệp; tuy nhiên, tôi muốn plugin hoạt động với bất kỳ chủ đề nào.

Làm cách nào để thay đổi nội dung của trang lưu trữ mà không cần thêm hoặc sửa đổi tệp chủ đề?

Chỉnh sửa: Tôi hiểu rằng tôi có thể sử dụng archive_templatemóc lọc. Tuy nhiên, tất cả điều này là thay thế mẫu chủ đề, vẫn cần phải cụ thể theo chủ đề. Ví dụ, chỉ là về tất cả các mẫu theme sẽ cần get_header, get_sidebarget_footerchức năng, nhưng những gì nên id của nội dung <div>được? Điều này là khác nhau trong mỗi chủ đề.

Những gì tôi muốn làm là thay thế chính nội dung đó bằng nội dung của riêng tôi và sử dụng nội dung đó thay cho trang lưu trữ cho loại bài đăng tùy chỉnh của tôi.

Câu trả lời:


12

Những gì bạn cần là móc template_includebộ lọc và tải có chọn lọc mẫu của bạn bên trong plugin.

Như một thực tiễn tốt, nếu bạn có kế hoạch phân phối plugin của mình, bạn nên kiểm tra xem archive-my_plugin_lesson.php(hoặc có thể myplugin/archive-lesson.php) có tồn tại trong chủ đề hay không, nếu không sử dụng phiên bản plugin.

Bằng cách này, người dùng dễ dàng thay thế mẫu thông qua chủ đề (hoặc chủ đề con) mà không cần chỉnh sửa mã plugin.

Đây là phương pháp được sử dụng bởi các plugin phổ biến, ví dụ WooCommmerce, chỉ để nói một tên.

add_filter('template_include', 'lessons_template');

function lessons_template( $template ) {
  if ( is_post_type_archive('my_plugin_lesson') ) {
    $theme_files = array('archive-my_plugin_lesson.php', 'myplugin/archive-lesson.php');
    $exists_in_theme = locate_template($theme_files, false);
    if ( $exists_in_theme != '' ) {
      return $exists_in_theme;
    } else {
      return plugin_dir_path(__FILE__) . 'archive-lesson.php';
    }
  }
  return $template;
}

Thông tin thêm về Codex cho


Điều này vẫn chỉ thay thế tệp mẫu của chủ đề, phải không? Tôi nên làm gì trong tập tin archive-learn.php của plugin? Nó sẽ cần phải khác nhau để làm việc với từng chủ đề. Ngay cả các chủ đề "Hai mươi" mặc định cũng không đồng ý về các thùng chứa div / phần bao quanh nội dung.
Ben Miller - Ghi nhớ Monica

7

Bạn có thể sử dụng archive_templatehook để xử lý nội dung của mẫu lưu trữ của một chủ đề, bằng cách sử dụng lược đồ bên dưới, nhưng rõ ràng bạn sẽ chỉ có thể xử lý một phần của các chủ đề ngoài đó, với điều kiện là một mẫu về cơ bản có thể chứa bất kỳ thứ cũ nào .

Lược đồ là tải mẫu vào một chuỗi ( $tpl_str) trong archive_templatebộ lọc, thay thế nội dung của bạn, bao gồm chuỗi (sử dụng thủ thuật eval( '?>' . $tpl_str );), sau đó trả về một tệp trống để includetrong "wp-gộp / template-loader.php" trở thành không-op.

Dưới đây là phiên bản mã bị hack mà tôi sử dụng trong một plugin, nhắm mục tiêu các mẫu "cổ điển" sử dụng get_template_partvà quan tâm đến việc xử lý các mẫu đơn hơn là lưu trữ, nhưng sẽ giúp bạn bắt đầu. Thiết lập là plugin có thư mục con được gọi là "mẫu" chứa tệp trống ("null.php") và mẫu nội dung (ví dụ: "content-single-posttype1.php", "content-archive-postype1.php") cũng như một mẫu quay lại "single.php" cho trường hợp đơn và sử dụng một phiên bản tùy chỉnh của giao diện get_template_partđó trong thư mục này.

define( 'MYPLUGIN_FOLDER', dirname( __FILE__ ) . '/' );
define( 'MYPLUGIN_BASENAME', basename( MYPLUGIN_FOLDER ) );

add_filter( 'single_template', 'myplugin_single_template' );
add_filter( 'archive_template', 'myplugin_archive_template' );

function myplugin_single_template( $template ) {
    static $using_null = array();

    // Adjust with your custom post types.
    $post_types = array( 'posttype1', );

    if ( is_single() || is_archive() ) {
        $template_basename = basename( $template );
        // This check can be removed.
        if ( $template == '' || substr( $template_basename, 0, 4 ) == 'sing' || substr( $template_basename, 0, 4 ) == 'arch' ) {
            $post_type = get_post_type();
            $slug = is_archive() ? 'archive' : 'single';
            if ( in_array( $post_type, $post_types ) ) {
                // Allow user to override.
                if ( $single_template = myplugin_get_template( $slug, $post_type ) ) {
                    $template = $single_template;
                } else {
                    // If haven't gone through all this before...
                    if ( empty( $using_null[$slug][$post_type] ) ) {
                        if ( $template && ( $content_template = myplugin_get_template( 'content-' . $slug, $post_type ) ) ) {
                            $tpl_str = file_get_contents( $template );
                            // You'll have to adjust these regexs to your own case - good luck!
                            if ( preg_match( '/get_template_part\s*\(\s*\'content\'\s*,\s*\'' . $slug . '\'\s*\)/', $tpl_str, $matches, PREG_OFFSET_CAPTURE )
                            || preg_match( '/get_template_part\s*\(\s*\'content\'\s*,\s*get_post_format\s*\(\s*\)\s*\)/', $tpl_str, $matches, PREG_OFFSET_CAPTURE )
                            || preg_match( '/get_template_part\s*\(\s*\'content\'\s*\)/', $tpl_str, $matches, PREG_OFFSET_CAPTURE )
                            || preg_match( '/get_template_part\s*\(\s*\'[^\']+\'\s*,\s*\'' . $slug . '\'\s*\)/', $tpl_str, $matches, PREG_OFFSET_CAPTURE ) ) {
                                $using_null[$slug][$post_type] = true;
                                $tpl_str = substr( $tpl_str, 0, $matches[0][1] ) . 'include \'' . $content_template . '\'' . substr( $tpl_str, $matches[0][1] + strlen( $matches[0][0] ) );
                                // This trick includes the $tpl_str.
                                eval( '?>' . $tpl_str );
                            }
                        }
                    }
                    if ( empty( $using_null[$slug][$post_type] ) ) {
                        // Failed to parse - look for fall back template.
                        if ( file_exists( MYPLUGIN_FOLDER . 'templates/' . $slug . '.php' ) ) {
                            $template = MYPLUGIN_FOLDER . 'templates/' . $slug . '.php';
                        }
                    } else {
                        // Success! "null.php" is just a blank zero-byte file.
                        $template = MYPLUGIN_FOLDER . 'templates/null.php';
                    }
                }
            }
        }
    }
    return $template;
}

function myplugin_archive_template( $template ) {
    return myplugin_single_template( $template );
}

Các tùy chỉnh get_template_part:

/*
 * Version of WP get_template_part() that looks in theme, then parent theme, and finally in plugin template directory (sub-directory "templates").
 * Also looks initially in "myplugin" sub-directory if any in theme and parent theme directories so that plugin templates can be kept separate.
 */
function myplugin_get_template( $slug, $part = '' ) {
    $template = $slug . ( $part ? '-' . $part : '' ) . '.php';

    $dirs = array();

    if ( is_child_theme() ) {
        $child_dir = get_stylesheet_directory() . '/';
        $dirs[] = $child_dir . MYPLUGIN_BASENAME . '/';
        $dirs[] = $child_dir;
    }

    $template_dir = get_template_directory() . '/';
    $dirs[] = $template_dir . MYPLUGIN_BASENAME . '/';
    $dirs[] = $template_dir;
    $dirs[] = MYPLUGIN_FOLDER . 'templates/';

    foreach ( $dirs as $dir ) {
        if ( file_exists( $dir . $template ) ) {
            return $dir . $template;
        }
    }
    return false;
}

Để hoàn thiện, đây là "back.php", sử dụng tùy chỉnh get_template_part:

<?php
get_header(); ?>

    <div id="primary" class="content-area">
        <div id="content" class="clearfix">
            <?php while ( have_posts() ) : the_post(); ?>

            <?php if ( $template = myplugin_get_template( 'content-single', get_post_type() ) ) include $template; else get_template_part( 'content', 'single' ); ?>

                <?php
                    // If comments are open or we have at least one comment, load up the comment template
                    if ( comments_open() || '0' != get_comments_number() ) :
                        comments_template();
                    endif;
                ?>

            <?php endwhile; ?>

        </div><!-- #content -->
    </div><!-- #primary -->

<?php get_sidebar(); ?>
<?php get_footer(); ?>

1

Tôi đã suy nghĩ về cùng một câu hỏi và đây là giải pháp giả định mà tôi đã đưa ra:

  • Trong plugin, tạo một shortcode đầu ra vòng lặp lưu trữ của bạn theo cách bạn muốn.
  • Khi tạo loại bài đăng tùy chỉnh, không kích hoạt tùy chọn 'archive'.
  • Thêm một biểu định kiểu kiểm soát tất cả các kiểu nội dung vòng lặp của bạn.

Khi kích hoạt plugin, hãy tạo một trang bằng wp_insert_post với tên là loại bài đăng và nội dung là shortcode.

Bạn có thể cung cấp các tùy chọn trong shortcode để xem xét kiểu bổ sung hoặc thêm các lớp vào thùng chứa bài để khớp với các kiểu tùy chỉnh hoặc chủ đề cụ thể. Người dùng cũng có thể thêm nội dung bổ sung trước / sau vòng lặp bằng cách chỉnh sửa trang.


Mặc dù tôi không phải là OP, tôi đã tìm kiếm một giải pháp cho cùng một vấn đề. Tôi đã theo dõi giải pháp giả thuyết của bạn và bây giờ tôi có thể xác nhận nó cũng hoạt động trong thực tế.
Lucio Crusca

Này tuyệt vời! Rất vui vì điều này hữu ích cho ai đó. Tôi đã hoàn toàn quên mất điều này.
SkyShab

0

Bạn có thể sử dụng bộ lọc single_template. Một ví dụ cơ bản được lấy từ Codex :

function get_custom_post_type_template($single_template) {
     global $post;

     if ($post->post_type == 'my_post_type') {
          $single_template = dirname( __FILE__ ) . '/post-type-template.php';
     }
     return $single_template;
}

add_filter( "single_template", "get_custom_post_type_template" );

Tôi nghĩ rằng móc lọc cho mẫu lưu trữ là archive_template, nhưng tôi không nghĩ rằng nó sẽ hoạt động cho những gì tôi đang cố gắng thực hiện. Tôi đã chỉnh sửa câu hỏi của mình với nhiều thông tin hơn.
Ben Miller - Ghi nhớ Monica
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.