在本教程系列的前两部分中,我们介绍了什么是动态页面模板以及为什么需要它们。 我们还研究了实现它们所需的代码。

在本系列的第三个也是最后一个教程中,我将创建两个可以在您自己的项目中使用的完全工作的动态页面模板的示例。 这些是经过特别选择的,可以轻松扩展以适合您自己的需求,并且可以启发您想到的任何其他类型的动态页面模板。

我们将很快介绍的两个动态页面模板是:

  • 简单联系表
  • 博客文章存档

除了实现我们的页面模板之外,我还将向您展示如何通过自定义CSS和JavaScript添加额外的修饰,以使交互对最终用户更加直观。

另外,我们将研究如何将页面模板用于任何帖子类型。 从WordPress 4.7开始 ,您可以指定与页面模板关联的帖子类型。 我们将看到您如何修改现有的动态页面模板以利用此新功能,使其适用于任何帖子类型。

我们将在本教程中介绍很多内容,因此让我们开始吧!

主题设定

就像在本教程系列的第2部分中一样,我们将再次使用WordPress 27子主题,以添加动态页面模板代码。 让我们从一个空白的子主题开始。

创建一个名为二twentyseventeen-child的子主题文件夹,并添加以下文件:

  • functions.php
  • style.css

在style.css内部,添加:

/*
 Theme Name:   Twenty Seventeen Child
 Description:  Twenty Seventeen Child Theme
 Author:       David Gwyer
 Template:     twentyseventeen
 Version:      0.1
 License:      GNU General Public License v2 or later
 License URI:  https://www.gnu.org/licenses/gpl-2.0.html
 Text Domain:  twenty-seventeen-child
*/

在functions.php ,添加:

<?php

/**
 * Twenty Seventeen child theme class.
 *
 * DPT = D[ynamic] P[age] T[emplates].
 */

class DPT_Twenty_Seventeen_Child {

    /**
    * Register hooks.
    */
    public function init() {
        add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_parent_theme_styles' ) );
    }

    /* Enqueue parent theme styles. */
    public function enqueue_parent_theme_styles() {
        wp_enqueue_style( 'twenty-seventeen-css', get_template_directory_uri() . '/style.css' );
    }
}

$ts_child_theme = new DPT_Twenty_Seventeen_Child();
$ts_child_theme->init();

像以前一样,将子主题添加到您的WordPress主题目录中。 如果不确定如何执行此操作,请参考本教程系列的第2部分。

现在,我们有一个工作的(空白)子主题,可以将其添加到动态页面模板代码中。

动态表单页面模板

动态页面模板的第一个实际实现是一个简单的联系表。 我们将添加以下字段:

  • 标题
  • 名称
  • 学科
  • 电子邮件
  • 电话号码

这些是除标题(标准HTML标题标签)之外的文本输入字段。

但是,在实现实际的页面模板之前,我们需要向页面编辑器添加自定义控件,以允许我们修改页面模板输出。 然后,当我们创建页面模板时,它将根据页面编辑器控件设置进行呈现。

在本系列教程的第2部分中,我提到了没有简单的方法可以直接将自定义控件直接添加到页面模板下拉菜单所在的“页面属性”元框中。

WordPress 3d动态标签云_WordPress 3d动态标签云

这意味着我们现在必须在其他位置添加动态页面模板控件。 稍后,我将向您展示如何通过一些CSS和JavaScript魔术来解决此限制。 但就目前而言,我们必须将自定义控件添加到单独的元框中。

在DPT_Twenty_Seventeen_Child类中,在init方法中注册两个新的动作钩子,以及一个名为page_template_meta_boxes的新方法。

<?php

/**
 * Register hooks.
 */
public function init() {
    add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_parent_theme_styles' ) );
    add_action( 'load-post.php', array( $this, 'page_template_meta_boxes' ) );
    add_action( 'load-post-new.php', array( $this, 'page_template_meta_boxes' ) );
}

/* Add meta box hook. */
public function page_template_meta_boxes() {
    add_action( 'add_meta_boxes', array( $this, 'add_page_template_meta_boxes' ) );
}

每当编辑或创建帖子(任何类型)时,都会运行load-post.php和load-post-new.php操作挂钩。 发生这种情况时,我们将注册另一个动作钩子add_meta_boxes ,它将触发我们的自定义元框的创建,这是通过add_page_template_meta_boxes回调函数完成的。 让我们现在实现该功能。

<?php

/* Register meta box. */
public function add_page_template_meta_boxes() {
    // Create meta box for our form dynamic page template
    add_meta_box(
        'form-page-template-meta-box',
        esc_html__( 'Form Page Template Meta Box', 'twenty-seventeen-child' ),
        array( $this, 'display_form_page_template_meta_box' ),
        'page',
        'side',
        'default'
    );
}

元框控件的实际呈现将通过display_form_page_template_meta_box回调函数进行处理,该函数在上面已指定为add_meta_box()的参数之一。

<?php

/* Render form meta box on the page editor. */
public function display_form_page_template_meta_box( $object ) {
    ?><p>Add controls here...</p><?php
}

现在,我已经添加了一些占位符文本,以便我们可以在页面编辑器上看到我们的新元框。

WordPress 3d动态标签云_php_02

记住,从前我们的表单页面模板将具有标题和四个文本字段。 我们可以选择多种方式来定制表单输出,但是在我们的情况下,让我们为每个字段添加复选框,以允许我们切换其可见性。 更新display_form_page_template_meta_box()以包括以下代码。

<?php

public function display_form_page_template_meta_box( $object ) {
    wp_nonce_field( basename( __FILE__ ), 'page_template_meta_box_nonce' );
    $heading = get_post_meta( $object->ID, 'pt_chk_form_heading', true );
    $name = get_post_meta( $object->ID, 'pt_chk_form_name', true );
    $subject = get_post_meta( $object->ID, 'pt_chk_form_subject', true );
    $email = get_post_meta( $object->ID, 'pt_chk_form_email', true );
    $phone = get_post_meta( $object->ID, 'pt_chk_form_phone', true );
    ?>

    <div id="form_pt_wrapper">
        <p>
            <input type="checkbox" name="pt_chk_form_heading" id="pt_chk_form_heading" value="1" <?php checked( $heading, true ); ?> /> <label for="pt_chk_form_heading"><?php _e( "Display Heading", 'twenty-seventeen-child' ); ?></label><br>
        </p>
        <p>
            <input type="checkbox" name="pt_chk_form_name" id="pt_chk_form_name" value="1" <?php checked( $name, true ); ?> /> <label for="pt_chk_form_name"><?php _e( "Display Name", 'twenty-seventeen-child' ); ?></label><br>
        </p>
        <p>
            <input type="checkbox" name="pt_chk_form_subject" id="pt_chk_form_subject" value="1" <?php checked( $subject, true ); ?> /> <label for="pt_chk_form_subject"><?php _e( "Display Subject", 'twenty-seventeen-child' ); ?></label><br>
        </p>
        <p>
            <input type="checkbox" name="pt_chk_form_email" id="pt_chk_form_email" value="1" <?php checked( $email, true ); ?> /> <label for="pt_chk_form_email"><?php _e( "Display Email", 'twenty-seventeen-child' ); ?></label><br>
        </p>
        <p>
            <input type="checkbox" name="pt_chk_form_phone" id="pt_chk_form_phone" value="1" <?php checked( $phone, true ); ?> /> <label for="pt_chk_form_phone"><?php _e( "Display Phone Number", 'twenty-seventeen-child' ); ?></label><br>
        </p>
    </div>
    <?php
}

我们包含一个安全性随机数字段,稍后将其保存到数据库中之前将对其进行验证。

注意:如果出于任何原因无法验证现时值,则不会保存设置。

然后,在将自定义表单字段输出到meta框之前,从数据库中检索当前表单值。

WordPress 3d动态标签云_WordPress 3d动态标签云_03

目前,帖子更新后将不会保存我们的复选框。 为了使表单设置持久化,我们需要在init()方法中注册一个新的钩子,该钩子在save_post操作期间触发,然后实现回调以手动更新post meta设置。

<php

/**
 * Register hooks.
 */
public function init() {
    add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_parent_theme_styles' ) );
    add_action( 'load-post.php', array( $this, 'page_template_meta_boxes' ) );
    add_action( 'load-post-new.php', array( $this, 'page_template_meta_boxes' ) );
    add_action( 'save_post', array( $this, 'save_page_template_meta' ), 10, 2 );
}
<?php

/* Save meta box data. */
public function save_page_template_meta( $post_id, $post ) {
    if ( ! ( isset( $_POST[ 'page_template_meta_box_nonce' ] ) && wp_verify_nonce( $_POST[ 'page_template_meta_box_nonce' ], basename( __FILE__ ) ) ) ) {
        return $post_id;
    }

    if ( ! current_user_can( 'edit_post', $post_id ) ) {
        return $post_id;
    }

    if( 'page' != $post->post_type ) {
        return $post_id;
    }

    $heading = isset( $_POST[ 'pt_chk_form_heading' ] ) ? $_POST[ 'pt_chk_form_heading' ] : '';
    update_post_meta( $post_id, 'pt_chk_form_heading', $heading );

    $name = isset( $_POST[ 'pt_chk_form_name' ] ) ? $_POST[ 'pt_chk_form_name' ] : '';
    update_post_meta( $post_id, 'pt_chk_form_name', $name );

    $subject = isset( $_POST[ 'pt_chk_form_subject' ] ) ? $_POST[ 'pt_chk_form_subject' ] : '';
    update_post_meta( $post_id, 'pt_chk_form_subject', $subject );

    $email = isset( $_POST[ 'pt_chk_form_email' ] ) ? $_POST[ 'pt_chk_form_email' ] : '';
    update_post_meta( $post_id, 'pt_chk_form_email', $email );

    $phone = isset( $_POST[ 'pt_chk_form_phone' ] ) ? $_POST[ 'pt_chk_form_phone' ] : '';
    update_post_meta( $post_id, 'pt_chk_form_phone', $phone );
}

一旦验证了表单现时值和用户权限,并进行了检查以确保我们使用的帖子类型正确,我们就可以测试发布的表单值并将其安全地保存到数据库中。

现在,我们的复选框已完全可用,因此我们可以继续实施实际的页面模板! 在根子主题文件夹内,添加一个名为page-templates的新文件夹,并向其中添加一个名为form-page-template.php的新文件。

将以下代码添加到新文件中以创建空白页模板。

<?php

/**
 * Template Name: Form Page Template
 *
 * @package WordPress
 * @subpackage Twenty_Seventeen
 * @since 1.0
 */

get_header(); ?>

<div class="wrap">

    <div id="primary" class="content-area">

        <main id="main" class="site-main" role="main">

            <!-- Add page template code here. -->

        </main><!-- #main -->

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

</div><!-- .wrap -->

<?php get_footer();

为了降低代码的复杂性,我们的联系表单不验证用户输入,并且我们承诺进行常规的表单检查和验证,因为我们只想专注于使表单输出动态化而没有多余的代码。

首先,我们需要检索动态联系表复选框值。

<?php

$heading = get_post_meta( get_the_ID(), 'pt_chk_form_heading', true );
$name = get_post_meta( get_the_ID(), 'pt_chk_form_name', true );
$subject = get_post_meta( get_the_ID(), 'pt_chk_form_subject', true );
$email = get_post_meta( get_the_ID(), 'pt_chk_form_email', true );
$phone = get_post_meta( get_the_ID(), 'pt_chk_form_phone', true );

然后我们可以添加表单代码。 每个表单字段都非常相似。 让我们看一下name字段代码。

<?php if ( ! empty ( $name ) ) : ?>
    <label for="cf_name"><?php _e( 'Name', 'twenty-seventeen-child' ); ?></label>
    <input type="text" name="cf_name" id="cf_name"><br>
<?php endif; ?>

我们从页面模板设置中测试复选框的值,并且仅在选中表单字段时输出它。 否则,将不会输出任何内容。 对于每个表单字段重复此操作。

提交表单后,我们会向网站管理员发送电子邮件,并在屏幕上显示一条消息。 综合所有这些,我们有了最终页面模板代码。

<?php

/**
 * Template Name: Form Page Template
 *
 * @package WordPress
 * @subpackage Twenty_Seventeen
 * @since 1.0
 */

get_header(); ?>

<div class="wrap">

    <div id="primary" class="content-area">

        <main id="main" class="site-main" role="main">

        <?php
        while ( have_posts() ) : the_post();

            $heading = get_post_meta( get_the_ID(), 'pt_chk_form_heading', true );
            $name = get_post_meta( get_the_ID(), 'pt_chk_form_name', true );
            $subject = get_post_meta( get_the_ID(), 'pt_chk_form_subject', true );
            $email = get_post_meta( get_the_ID(), 'pt_chk_form_email', true );
            $phone = get_post_meta( get_the_ID(), 'pt_chk_form_phone', true );

            // Form submission handler
            if ( isset( $_POST['cf_submitted'] ) ) {
                $admin_email = get_bloginfo( 'admin_email' );
                $cf_subject = trim( $_POST['cf_subject'] );
                $headers = "From: me@mysite.com\r\n";
                mail( $admin_email, $subject, 'Dynamic contact form submitted!', $headers );
                echo "<p>Mail sent successfully!</p>";
            }
            ?>

            <form action="<?php the_permalink(); ?>" method="post">

                <?php if ( ! empty( $heading ) ) : ?>
                    <h2>Dynamic Form Page Template!</h2>
                <?php endif; ?>

                <?php if ( ! empty( $name ) ) : ?>
                    <label for="cf_name"><?php _e( 'Name', 'twenty-seventeen-child' ); ?></label>
                    <input type="text" name="cf_name" id="cf_name"><br>
                <?php endif; ?>

                <?php if ( ! empty( $subject ) ) : ?>
                    <label for="cf_subject"><?php _e( 'Subject', 'twenty-seventeen-child' ); ?></label>
                    <input type="text" name="cf_subject" id="cf_subject"><br>
                <?php endif; ?>

                <?php if ( ! empty( $email ) ) : ?>
                    <label for="cf_email"><?php _e( 'Email', 'twenty-seventeen-child' ); ?></label>
                    <input type="email" name="cf_email" id="cf_email"><br>
                <?php endif; ?>

                <?php if ( ! empty( $phone ) ) : ?>
                    <label for="cf_phone"><?php _e( 'Phone Number', 'twenty-seventeen-child' ); ?></label>
                    <input type="tel" name="cf_phone" id="cf_phone"><br>
                <?php endif; ?>

            <p><input type="hidden" name="cf_submitted" id="cf_submitted" value="true"><input class="submit button" type="submit" value="<?php _e( 'Submit Form', 'twenty-seventeen-child' ); ?>"></p>
        
            </form>
        
        <?php
        endwhile; // End of the loop.
        ?>

        </main><!-- #main -->

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

</div><!-- .wrap -->

<?php get_footer();

要测试一切正常,请确保选中所有表单页面模板复选框并更新帖子。 然后看看前端的页面模板。

WordPress 3d动态标签云_WordPress 3d动态标签云_04

现在尝试取消选中某些表单页面模板复选框。 仅输出指定的字段。 您完全可以控制表单的显示方式! 在下面的屏幕快照中,我仅选中了电子邮件和电话复选框。

WordPress 3d动态标签云_python_05

注意:如果您在本地WordPress环境中工作,则mail功能实际上可能不会发送电子邮件。 仅当您已设置并运行邮件服务器时,它才起作用。

可以轻松扩展该窗体以添加任意数量的任何类型的控件。 例如,您可以在表单中添加可选的CAPTCHA字段 ,或者可以指定输出字段的顺序,甚至可以指定表单标题/标签的文本。 这里的要点是,您可以根据需要使用动态页面模板来自定义表单。 可能性无穷无尽!

组织我们的页面模板控件

您可能已经注意到,动态页面模板的管理控件存在几个可用性问题。 从功能上讲还不错,但理想情况下,动态页面模板控件应与页面模板下拉菜单位于相同的meta框中。

WordPress 3d动态标签云_javascript_06

请记住,我们必须首先将页面模板控件添加到单独的meta框的原因是因为当前没有WordPress挂钩可用于将自定义控件直接添加到页面模板meta框。

另外,当选择了动态页面模板时,我们只希望与该模板关联的控件可见。 我们可以通过向页面编辑器添加一些自定义CSS和JavaScript来完成这两个要求。

具体来说,我们需要:

  • 隐藏表单元框。
  • 等待管理员编辑器页面完全加载。
  • 将表单控件移至“页面属性”元框。
  • 如果选择了关联的页面模板,则仅显示管理表单控件。

首先将css和js文件夹添加到您的子主题根文件夹中。 在css文件夹中,创建一个style.css文件,在js文件夹中,创建一个script.js文件。 不过,您可以将这些命名为任何名称。 只要记住,如果要记下文件名,并在入队脚本代码中替换它们即可。

然后,我们只需要在排队上的两个文件页面编辑器屏幕。 我们不希望它们添加到所有管理页面。 在init()方法中注册一个新的动作挂钩,以在管理页面上加载脚本,并添加回调函数以使脚本文件入队。

<?php

/**
 * Register hooks.
 */
public function init() {
    add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_parent_theme_styles' ) );
    add_action( 'load-post.php', array( $this, 'page_template_meta_boxes' ) );
    add_action( 'load-post-new.php', array( $this, 'page_template_meta_boxes' ) );
    add_action( 'save_post', array( $this, 'save_page_template_meta' ), 10, 2 );
    add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_editor_scripts' ) );
}

public function enqueue_editor_scripts($hook) {
    global $post_type;

    if ( 'page' != $post_type ) {
        return;
    }


    if ( 'post-new.php' != $hook && 'post.php' != $hook) {
        return;
    }

    wp_enqueue_script( 'dpt_script', get_stylesheet_directory_uri() . '/js/script.js', array( 'jquery' ) );
    wp_enqueue_style( 'dpt_styles', get_stylesheet_directory_uri() . '/css/style.css' );
}

注意我们如何定位page发布类型,然后定位post-new.php或post.php管理页面。 因此,基本上,除非我们使用页面编辑器,否则我们的脚本将不会被加载,而这正是我们想要的。

现在让我们开始添加CSS和JavaScript,以自定义表单页面模板控件。 首先,通过将其添加到style.css中,用CSS隐藏整个表单元框:

#form-page-template-meta-box {
    display: none;
}

我们可以使用JavaScript完成此操作,但是我们希望表单元框立即隐藏。 如果我们通过JavaScript做到这一点,则必须等到页面加载完毕,并且您会在屏幕上看到一个小小的闪烁,因为该meta框呈现在屏幕上,然后被JavaScript隐藏。 因此在这种情况下使用CSS更好。

现在使用JavaScript。 将此添加到script.js 。

jQuery(document).ready(function ($) {

    var pt = $( "#page_template" );
    var form_controls = $( "#form_pt_wrapper" );

    // Move form controls to 'Page Attributes' meta box and hide them by default
    form_controls.insertAfter( '#page_template' ).hide();

    function displayControls( ptStr, sel ) {
        if ( ptStr !== pt.val() ) {
            sel.hide();
        } else {
            sel.toggle();
        }
    }

    // Call on page load
    displayControls( 'page-templates/form-page-template.php', form_controls );

    // Call every time drop down changes
    pt.on( 'change', function () {
        displayControls( this.value, form_controls );
    });

});

我将不涉及JavaScript的大量细节,但这里是概述。

我们首先缓存几个CSS选择器,然后将管理表单控件移至“ Page Attributes元框。 然后,我们有一个displayControls()函数,该函数根据页面模板下拉菜单的当前值隐藏或显示表单控件。 我们在页面加载时调用displayControls() ,然后每次更改下拉菜单时都确保始终保持同步。

添加CSS和JavaScript后,表单页面模板控件现在显示在正确的元框中,并且仅在选择了关联的页面模板时显示。

WordPress 3d动态标签云_python_07

这看起来好多了,并且对用户来说更直观。 因为可以在WordPress管理屏幕上移动meta框,所以我们的动态页面模板控件不一定位于页面模板下拉菜单附近! 我们已经以一种优雅的方式解决了这个问题,以确保我们的控件始终直接出现在页面模板下拉菜单的下方!

博客文章动态页面模板

我们的下一个动态页面模板显示您最新博客文章的列表。 但是,我们不仅会列出所有帖子,还将实现一个列表框(类似于下拉列表),使您可以选择帖子类别。 不仅如此,您还可以选择多个帖子类别。

首先在add_page_template_meta_boxes()中添加一个新的元框。

<?php

// Create meta box for our blog posts dynamic page template
add_meta_box(
    'blog-page-template-meta-box',
    esc_html__( 'Blog Page Template Meta Box', 'twenty-seventeen-child' ),
    array( $this, 'display_blog_page_template_meta_box' ),
    'page',
    'side',
    'default'
);

现在,我们需要实现回调函数以呈现我们的元框。

<?php

/* Render form meta box on the page editor. */
public function display_blog_page_template_meta_box( $object ) {
 
    $blog_category = get_post_meta( $object->ID, 'blog_category', true );
    $categories = get_categories();
    ?>

    <div id="blog_pt_wrapper">
        <label for="blog_category[]"><?php _e( 'Choose categories', 'twenty-seventeen-child' ); ?>:</label>
        <select style="height:inherit;" name="blog_category[]" multiple="multiple" size="10">
        <?php
            foreach ( $categories as $category ) {
                printf(
                    '<option value="%1$s" %2$s>%3$s (%4$s)</option>',
                    esc_attr( $category->cat_ID ),
                    esc_attr( selected( $category->cat_ID, $this->q($category->cat_ID, $blog_category) ) ),
                    esc_html( $category->cat_name ),
                    esc_html( $category->category_count )
                );
            }
        ?>
        </select>
    </div>

<?php
}

让我们分解一下。 我们首先定义一个变量,以保存从上次更新帖子以来选择的帖子类别列表(如果有)。 另一个变量存储所有现有类别的数组。

注意:我们已经在先前的表单页面模板中拥有一个noce字段,因此我们不需要在此处使用另一个字段,因为我们位于同一管理页面上。

然后,我们遍历网站类别的列表,并随即填充一个下拉控件。 再次选择以前选择的任何类别,以使所有内容保持同步。

但是,您可能已经注意到, selected()的参数之一是函数调用。 通常,我们只是使用selected()比较两个值来确定是否将当前项目标记为选中状态。 但是,因为我们可以选择多个类别,所以我们的数据库设置始终是一组值的数组(即使实际上我们只选择了一个类别)。

函数q()是一个辅助函数,它使我们可以根据保存的类别数组检查当前列表项。

<?php

public function q($sel, $opt) {
    if( is_array($opt) && in_array($sel, $opt) ) {
        return $sel;
    }
}

对于每个类别,类别ID与保存的类别数组一起传递到q() 。 如果当前类别在已保存类别的列表中,则当前类别将返回到selected()并将与第一个参数匹配。 这将导致selected()将当前类别标记为选中。 这是为单个控件处理多个选项的一种优雅方法。

现在我们需要做的就是更新save_page_template_meta()来处理保存博客文章类别。 添加此代码即可做到这一点。

<?php

// Save blog page template controls
$category = isset( $_POST[ 'blog_category' ] ) ? $_POST[ 'blog_category' ] : '';
update_post_meta( $post_id, 'blog_category', $category );

现在,我们需要创建博客帖子页面模板。 在您的子主题page-templates文件夹内,创建一个名为blog-page-template.php的新文件,并添加以下代码。

<?php

/**
 * Template Name: Blog Page Template
 *
 * @package WordPress
 * @subpackage Twenty_Seventeen
 * @since 1.0
 */

get_header(); ?>

<div class="wrap">

    <div id="primary" class="content-area">

        <main id="main" class="site-main" role="main">

        <?php
        $paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
        $category = get_post_meta( get_the_id(), 'blog_category', true );

        if( is_array($category) ) {
            $category = implode(",", $category);
        }

        if( !empty($category) ) {
            $cat = $category;
        } else {
            $cat = 0;
        }

        $query_args = array(
            'paged' => $paged,
            'cat' => $cat,
            'orderby' => 'date',
            'order' => 'DESC',
            'post_type' => 'post'
        );

        $blog_posts = new WP_Query($query_args);
        ?>

        <?php if ( $blog_posts->have_posts() ) : ?>

            <?php while ( $blog_posts->have_posts() ) : $blog_posts->the_post(); ?>
                <?php get_template_part( 'template-parts/post/content', get_post_format() ); ?>
            <?php endwhile; // end of the loop. ?>

        <?php endif; ?>

        </main><!-- #main -->

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

</div><!-- .wrap -->

<?php get_footer();

与我们之前的动态页面模板的唯一真正区别是<main> HTML标记内的代码,因此让我们现在仔细看一下。

我们首先设置paged查询变量的值,该值用于显示多个页面上的帖子,具体取决于从WordPress查询返回的页面数。 然后,我们获得在页面编辑器元框中选择的所有类别。 类别数组将转换为字符串,如果为空,则提供默认值。 然后创建一个新的WordPress查询,并在标准循环中输出结果。

这里的关键是,我们可以通过在页面编辑器meta框中进行选择,来精确控制将哪些类别传递给查询对象。

现在,我们要做的就是隐藏Blog类别元框,并将列表控件移至“ Page Attributes元框。 就像我们以前一样。

在style.css内部,更新样式以隐藏博客文章元框:

#form-page-template-meta-box, #blog-page-template-meta-box {
    display: none;
}

script.js文件需要添加更多代码。 这是完全更新的文件。

jQuery(document).ready(function ($) {

    var pt = $( "#page_template" );
    var form_controls = $( "#form_pt_wrapper" );
    var blog_post_controls = $( "#blog_pt_wrapper" );

    // Move form controls to 'Page Attributes' meta box and hide them by default
    form_controls.insertAfter( '#page_template' ).hide();
    blog_post_controls.insertAfter( '#page_template' ).hide();

    function displayControls( ptStr, sel ) {
        if ( ptStr !== pt.val() ) {
            sel.hide();
        } else {
            sel.toggle();
        }
    }   

    // Call on page load
    displayControls( 'page-templates/form-page-template.php', form_controls );

    displayControls( 'page-templates/blog-page-template.php', blog_post_controls );

    // Call every time drop down changes
    pt.on( 'change', function () {

        var controls;

        if( this.value === 'page-templates/form-page-template.php' ) {
            controls = form_controls;
            blog_post_controls.hide();
        } else if( this.value === 'page-templates/blog-page-template.php' ) {
            controls = blog_post_controls;
            form_controls.hide()
        } else {
            // hide all
            blog_post_controls.hide()
            form_controls.hide();
        }

        displayControls( this.value, controls );
    });

});

值得注意的大多数更改都在.on('change')函数中。 因为我们现在有多个动态页面模板,所以我们必须进行测试以查看是否从下拉列表中选择了哪个模板,然后将其在相应的元素选择器中传递给displayControls() 。

除了选中的页面模板控件之外,我们还需要隐藏所有其他页面模板控件。 如果显示了默认页面模板,我们将隐藏所有页面模板控件。 JavaScript代码可以进一步优化,但是由于我们只有两个动态页面模板处于活动状态,因此它可以很好地满足我们的需求。

WordPress 3d动态标签云_python_08

进行了这些修改之后,我们现在有了两个可运行的动态页面模板,它们的每个相关控件都直接显示在页面模板下拉菜单的下方。

每个人的页面模板

之前我曾提到过,在WordPress 4.7+中,如何现在可以将页面模板分配给任何帖子类型。 在WordPress 4.7之前,您只能将它们分配给页面,但不能再分配了!

您所要做的就是在页面模板标题的注释栏中添加一行,并指定要使用页面模板的帖子类型的逗号分隔列表。

<?php

Template Post Type: page, movie, notes

帖子类型名称必须与首次注册该帖子类型时输入的子弹名称相同,否则它将被忽略。

因此,我们可以显示任何帖子类型的页面模板,但是动态页面模板呢? 仅需少量修改,就可以支持这些修改。 让我们看看需要什么。

幸运的是,除了在页面模板的顶部添加一行代码之外,所有必要的更改都在一个文件中: functions.php 。

首先,我们不仅需要在页面上加入动态页面模板CSS和JavaScript,还需要为所有帖子类型加入动态页面模板。 因此,在enqueue_editor_scripts() ,我们可以执行类似的操作。

<?php

if ( 'page' != $post_type && 'movie' != $post_type ) {
    return;
    }

现在,动态页面模板脚本将被加载到页面和电影自定义帖子类型上。

接下来,在add_page_template_meta_boxes() ,更新要在自定义帖子类型上显示的add_meta_box()每个实例。 不仅可以指定page ,我们还可以传递所需的帖子类型数组。

<?php

add_meta_box(
    'form-page-template-meta-box',
    esc_html__( 'Form Page Template Meta Box', 'twenty-seventeen-child' ),
    array( $this, 'display_form_page_template_meta_box' ),
    Array( 'page', 'movie' ),
    'side',
    'default'
);

最后,更新save_page_template_meta()以支持多种帖子类型,就像对enqueue_editor_scripts() 。 就是这样!

仅需遵循以下几步,您就可以修改动态页面模板以适用于任何帖子类型。

注意:对于运行版本低于4.7版的任何WordPress网站,“ Template Post Type标头文本将被忽略,默认情况下将显示所有页面模板。 如果不希望这样做,则可以添加自定义代码以使页面模板向后兼容。

<?php

function makewp_exclude_page_templates( $post_templates ) {

    if ( version_compare( $GLOBALS['wp_version'], '4.7', '<' ) ) {
        unset( $post_templates['templates/my-full-width-post-template.php'] );
    }

    return $post_templates;
}
add_filter( 'theme_page_templates', 'makewp_exclude_page_templates' );

该摘录摘自Make WordPress博客,您可以在其中找到有关向后兼容性和新页面模板功能的更多详细信息 。

结论

在本系列教程的最后一部分中,我们已经介绍了很多基础知识。 具体来说,我们已经实现了两个完全可以使用的动态页面模板,并使用了自定义CSS和JavaScript来增强用户体验。

即使本教程系列中介绍的动态帖子类型相对简单,将其扩展以创建强大而灵活的页面模板也将非常容易。 添加一些下一代功能的范围如此之大。 而且,从WordPress 4.7开始,您也不仅限于为页面开发它们。

如果您正在寻找其他实用程序来帮助您构建不断增长的WordPress工具集或用于研究代码并变得更加精通WordPress的代码,请不要忘记查看Envato Market中提供的功能 。

本教程系列是否启发您创建动态页面模板? 如果是这样,请在下面的评论中告诉我。 我很想听听您的想法以及您如何在自己的项目中使用它们。

翻译自: https://code.tutsplus.com/tutorials/dynamic-page-templates-in-wordpress-part-3--cms-28514