WordPress

WordPress 讀取模板 (template) 的方式

從網路上整理出一些 WordPress 載入範本頁面的方式,順便也將 Source Code 附上,簡單比較一下差別。

先說結論,對於佈景主題的範本載入,直接用 get_template_part() 就好,大部分的主題也是使用這個方式去載入範本。

1. 傳統 PHP 方法

PHP 原生方法,如果不想用 WordPress 的 function,就是用 include()include_once()require()require_once() 去載入。

不會檢查路徑,必須使用完整範本路徑

include(TEMPLATEPATH . '/template-name.php');

2. load_template()

WordPress 的函數,載入範本用的,從下方 Source 中可以發現,就是將原本 PHP 函數包裝起來。

不會檢查範本資料,所以必須使用完整範本路徑

load_template(TEMPLATEPATH . '/template-name.php');
function load_template( $_template_file, $require_once = true, $args = array() ) {
    global $posts, $post, $wp_did_header, $wp_query, $wp_rewrite, $wpdb, $wp_version, $wp, $id, $comment, $user_ID;

    if ( is_array( $wp_query->query_vars ) ) {
        /*
         * This use of extract() cannot be removed. There are many possible ways that
         * templates could depend on variables that it creates existing, and no way to
         * detect and deprecate it.
         *
         * Passing the EXTR_SKIP flag is the safest option, ensuring globals and
         * function variables cannot be overwritten.
         */
        // phpcs:ignore WordPress.PHP.DontExtract.extract_extract
        extract( $wp_query->query_vars, EXTR_SKIP );
    }

    if ( isset( $s ) ) {
        $s = esc_attr( $s );
    }

    if ( $require_once ) {
        require_once $_template_file;
    } else {
        require $_template_file;
    }
}

3. locate_template()

WordPress 的函數,將第二項的 load_template() 包裝起來,並加入路徑搜索功能,所以可以使用相對路徑

如果有找到對應的範本文件,就會立即回傳文件路徑位置。

locate_template(array(
    'download.php',
    'custom-download.php',
    'mytheme-download.php'
), true);
function locate_template( $template_names, $load = false, $require_once = true, $args = array() ) {
    $located = '';
    foreach ( (array) $template_names as $template_name ) {
        if ( ! $template_name ) {
            continue;
        }
        if ( file_exists( STYLESHEETPATH . '/' . $template_name ) ) {
            $located = STYLESHEETPATH . '/' . $template_name;
            break;
        } elseif ( file_exists( TEMPLATEPATH . '/' . $template_name ) ) {
            $located = TEMPLATEPATH . '/' . $template_name;
            break;
        } elseif ( file_exists( ABSPATH . WPINC . '/theme-compat/' . $template_name ) ) {
            $located = ABSPATH . WPINC . '/theme-compat/' . $template_name;
            break;
        }
    }

    if ( $load && '' !== $located ) {
        load_template( $located, $require_once, $args );
    }

    return $located;
}

4. get_query_template()

一樣是 WordPress 的函數,會將第三項的 load_template() 包裝起來,能夠不用副檔名 (file extension name) 的情況下搜索範本文件,並會*回傳完整路徑

還有一點與 load_template() 不同,需要指定頁面類型,例如下面範例載入 404 範本頁面時,通過 get_query_template() 可以取得副檔名供 include() 使用。

include(get_404_template());

// the same
include(get_query_template('404'));

Note: 可以搜索的清單可以看 Source Code 註解。

function get_query_template( $type, $templates = array() ) {
    $type = preg_replace( '|[^a-z0-9-]+|', '', $type );

    if ( empty( $templates ) ) {
        $templates = array( "{$type}.php" );
    }

    /**
     * Filters the list of template filenames that are searched for when retrieving a template to use.
     *
     * The dynamic portion of the hook name, `$type`, refers to the filename -- minus the file
     * extension and any non-alphanumeric characters delimiting words -- of the file to load.
     * The last element in the array should always be the fallback template for this query type.
     *
     * Possible hook names include:
     *
     *  - `404_template_hierarchy`
     *  - `archive_template_hierarchy`
     *  - `attachment_template_hierarchy`
     *  - `author_template_hierarchy`
     *  - `category_template_hierarchy`
     *  - `date_template_hierarchy`
     *  - `embed_template_hierarchy`
     *  - `frontpage_template_hierarchy`
     *  - `home_template_hierarchy`
     *  - `index_template_hierarchy`
     *  - `page_template_hierarchy`
     *  - `paged_template_hierarchy`
     *  - `privacypolicy_template_hierarchy`
     *  - `search_template_hierarchy`
     *  - `single_template_hierarchy`
     *  - `singular_template_hierarchy`
     *  - `tag_template_hierarchy`
     *  - `taxonomy_template_hierarchy`
     *
     * @since 4.7.0
     *
     * @param string[] $templates A list of template candidates, in descending order of priority.
     */
    $templates = apply_filters( "{$type}_template_hierarchy", $templates );

    $template = locate_template( $templates );

    $template = locate_block_template( $template, $type, $templates );

    /**
     * Filters the path of the queried template by type.
     *
     * The dynamic portion of the hook name, `$type`, refers to the filename -- minus the file
     * extension and any non-alphanumeric characters delimiting words -- of the file to load.
     * This hook also applies to various types of files loaded as part of the Template Hierarchy.
     *
     * Possible hook names include:
     *
     *  - `404_template`
     *  - `archive_template`
     *  - `attachment_template`
     *  - `author_template`
     *  - `category_template`
     *  - `date_template`
     *  - `embed_template`
     *  - `frontpage_template`
     *  - `home_template`
     *  - `index_template`
     *  - `page_template`
     *  - `paged_template`
     *  - `privacypolicy_template`
     *  - `search_template`
     *  - `single_template`
     *  - `singular_template`
     *  - `tag_template`
     *  - `taxonomy_template`
     *
     * @since 1.5.0
     * @since 4.8.0 The `$type` and `$templates` parameters were added.
     *
     * @param string   $template  Path to the template. See locate_template().
     * @param string   $type      Sanitized filename without extension.
     * @param string[] $templates A list of template candidates, in descending order of priority.
     */
    return apply_filters( "{$type}_template", $template, $type, $templates );
}

5. get_template_part()

最後是最常用也最常看到的 WordPress 函數,一樣會去包裝 locate_template(),通常會用於 body tag 裡面,所以可以使用這個方式來製作各個範本零件 (template part),最後再將其整合在你的佈景主題中。

function get_template_part( $slug, $name = null, $args = array() ) {
    /**
     * Fires before the specified template part file is loaded.
     *
     * The dynamic portion of the hook name, `$slug`, refers to the slug name
     * for the generic template part.
     *
     * @since 3.0.0
     * @since 5.5.0 The `$args` parameter was added.
     *
     * @param string      $slug The slug name for the generic template.
     * @param string|null $name The name of the specialized template.
     * @param array       $args Additional arguments passed to the template.
     */
    do_action( "get_template_part_{$slug}", $slug, $name, $args );

    $templates = array();
    $name      = (string) $name;
    if ( '' !== $name ) {
        $templates[] = "{$slug}-{$name}.php";
    }

    $templates[] = "{$slug}.php";

    /**
     * Fires before a template part is loaded.
     *
     * @since 5.2.0
     * @since 5.5.0 The `$args` parameter was added.
     *
     * @param string   $slug      The slug name for the generic template.
     * @param string   $name      The name of the specialized template.
     * @param string[] $templates Array of template files to search for, in order.
     * @param array    $args      Additional arguments passed to the template.
     */
    do_action( 'get_template_part', $slug, $name, $templates, $args );

    if ( ! locate_template( $templates, true, false, $args ) ) {
        return false;
    }
}

Refer

2 則留言

留下一個回覆

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *