近期我寫了一套給開發者&自己用的套件,主要功能是簡化外掛開發時載入佈景主題範本的需求,以往在學習開發佈景主題時,常會看到上面這張圖來解釋 WordPress 範本的繼承關係:
這張圖很完整的說明當使用者造訪特定頁面時會對應的範本檔,這方面的知識可以參考 WordCamp Taipei 2019 的這場分享:「Barry Lin: WordPress 初學者世界,佈景結構概念談!」。既然範本檔主要是佈景主題在設計前台畫面使用的,跟開發外掛有什麼關係呢?事實上在實務中還滿常碰到的,像是如果你的外掛有新增自定義文章,就會需要設計該文章的範本,可能是文章內頁或是彙整頁。
此外,如果要在外掛中提供可重用的頁面範本,或是有針對 WooCommerce 的頁面進行某種程度的客製化,你的外掛都會需要載入範本,由於這些範本中的功能都是外掛所提供的,所以基本上不適合將它放在佈景主題的資料夾裡面,統一放在外掛目錄才好管理與維護,以下就外掛載入範本檔的具體方法進行介紹。
外掛結構
我們以一個叫做 wp-template 的範例外掛來說明,首先看到它的資料夾結構如下:
├── composer.json
├── composer.lock
├── src
├── templates
│ ├── archive-book.php
│ ├── author.php
│ ├── page-slug.php
│ ├── page-test.php
│ ├── single-book.php
│ ├── template-demo.php
│ ├── template-test.php
│ └── woocommerce
│ └── checkout
│ └── form-checkout.php
├── vendor
└── wp-template.php
templates 資料夾放的是對應的範本檔,可以看到有各種不同類型的範本:
Page Template
以 template 開頭的檔案如 template-demo.php
跟 template-test.php
是可重用的頁面範本檔,可以讓使用者在後台的頁面管理中選擇使用。
Page Slug Remplate
以 page 開頭的檔案如 page-slug.php
以及 page-test.php
,這會在頁面的網址代稱為 slug 或是 test 的時候所使用。
Post Type Template
該外掛註冊了一個自定義文章叫做 book,該文章的內頁以及彙整頁範本分別為 single-book.php
與 archive-book.php
。
WordPress Template
假設該外掛有一個需求是要客製化作者頁面,對應到的範本是 author.php
,透過它就可以複寫佈景主題內建的作者頁面。
WooCommerce Template
另外如果要複寫 WooCommerce 的相關頁面,對應的是 WooCommerce 資料夾,資料夾的結構與檔案名稱要跟預設的一樣,這邊我們假設要客製化結帳頁面,因此需要的檔案是 form-checkout.php
。
取代範本的邏輯
WordPress 提供了一個動態勾點叫做 ${type}_template
,可以判斷在不同的頁面下替換不同的範本,會回傳一個路徑,我們就是透過這個路徑來修改載入黨案,所有可使用的類型有:
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
舉替換作者頁為例,只要透過 author_template
這個勾點去載入外掛中的範本,就可以進行替換:
add_filter( 'author_template', 'set_author_template', 99, 1 );
function set_author_template( $template ) {
$template = plugin_dir_path( __FILE__ ) . 'templates/author.php';
return $template;
}
比較不一樣的是 WooCommerce,它用自己的勾點 wc_get_template
來處理,它帶有三個參數,可以讓我們進一步檢查外掛中是否有包含 WooCommerce 對應的範本檔,如果沒有的話就使用內建的範本:
add_filter( 'wc_get_template', 'intercept_wc_template', 99, 3 );
function intercept_wc_template( $template, $template_name, $template_path ) {
$dir = trailingslashit( plugin_dir_path( __FILE__ ) ) . 'templates/woocommerce/';
$path = $dir . $template_name;
return file_exists( $path ) ? $path : $template;
}
wp-template
由於在不同的情境下使用的勾點不同,用法也有些差異,因此我寫了一個介面來統一操作習慣,這樣之後就不需要再記要用哪個勾點了,該套件名稱為 wp-template,先使用 composer 進行安裝:
$ composer require oberonlai/wp-template
接下來在宣告類別時把範本的路徑帶入:
use ODS\Template;
$template = new Template( plugin_dir_path( __FILE__ ) . 'templates/' );
如果你的範本目錄是放在 yourpluign/views
底下,那就是變成 new Template( plugin_dir_path( __FILE__ ) . 'views/' );
即可,記得最後的斜線不要漏掉。
新增可重用的頁面範本檔
使用 add_page()
方法來建立,帶有兩個參數:
- $file – 範本檔案名稱
- $name – 顯示在後台頁面管理範本下拉選單中的文字
範例如下:
use ODS\Template;
$template = new Template( plugin_dir_path( __FILE__ ) . 'templates/' );
$template->add_page( 'template-demo.php', '我的範本' );
要增加多個範本就呼叫多次 add_page()
:
$template->add_page( 'template-demo.php', '我的範本' );
$template->add_page( 'template-test.php', '他的範本' );
$template->add_page( 'template-your.php', '你的範本' );
新增頁面代稱範本
使用 add_page_slug()
方法建立,帶有兩個參數:
- $file – 範本檔案名稱
- $slug – 頁面代稱
範例如下:
use ODS\Template;
$template = new Template( plugin_dir_path( __FILE__ ) . 'templates/' );
$template->add_page_slug( 'page-test.php', 'test' );
這樣當使用者造訪頁面 https://example.com/test 的時候使用的就會是外掛的範本。
新增自定義文章範本
使用 add_post()
方法建立,帶有三個參數:
- $file – 範本檔案名稱
- $type – 自定義文章名稱
- $position – 所在位置
範例如下:
use ODS\Template;
$template = new Template( plugin_dir_path( __FILE__ ) . 'templates/' );
$template->add_post( 'single-book.php', 'book', 'single' );
$template->add_post( 'archive-book.php', 'book', 'archive' );
複寫 WordPress 佈景主題範本
使用這個方法要特別小心,理論上要從外掛修改佈景主題的內容,請優先使用勾點來處理,複寫範本檔可能會造成後續維護上的困難,除非你有把握這個網站永遠都會是你經手,或是有清楚的交接文件,不然會害接手的人怎麼改都改不動。
使用 add_wp()
即可複寫,這個勾點的執行順序是 99,因此上述的問題要特別小心,該方法帶有兩個參數:
- $file – 範本檔案名稱
- $position – 所在位置
範例如下:
use ODS\Template;
$template = new Template( plugin_dir_path( __FILE__ ) . 'templates/' );
$template->add_wp( 'author.php', 'author' ); // 取代作者葉
$template->add_wp( '404.php', '404' ); // 取代 404 頁
複寫 WooCommerce 範本
使用 add_woocommerce()
方法建立,與 add_wp()
一樣,優先使用勾點而非透過範本去修改頁面內容,因為 WooCommerce 常常會釋出範本更新,如果官方有更新而我們自己客製化的版本沒有跟上,可能就會發生預期外的狀況。
該方法不用帶任何參數,它會自動抓 templates/woocommerce
資料夾裡面的檔案,而該資料夾的結構記得要完全比照 WooCommerce 的規則,也就是 plugins/woocommerce/templates
裡面的結構以及檔案命名。
範例如下:
use ODS\Template;
$template = new Template( plugin_dir_path( __FILE__ ) . 'templates/' );
$template->add_woocommerce();
完整用法請參考:https://github.com/oberonlai/wp-template
使用這個套件可以一致性的載入我們所需的範本檔,減少記憶不同的用法,歡迎大家用看看,使用上有任何問題也可以跟我說!