WordPress 使用自訂欄位 _wp_page_template 記錄頁面所用模板。本文解析核心機制,提供透過模板檔案名稱反查頁面 ID 的實戰函數,解決「動態獲取特定功能頁面連結」的常見需求。
| 模板類型 | _wp_page_template 值 | 說明 |
|---|---|---|
| 預設模板 (page.php) | default | 若從未更改模板,此欄位不存在 |
| 主題根目錄模板 | page-login.php | 檔案名稱,不含路徑 |
| 子目錄模板 | templates/page-login.php | 含相對路徑 |
| 區塊主題模板 | wp:template-slug | 區塊編輯器模板 |
關鍵點:欄位名以下劃線開頭 → 屬於「隱藏自訂欄位」,後台 UI 不顯示。
/**
* 根據頁面模板檔案名稱獲取發布狀態的頁面 ID
* @param string $template 模板檔案名稱 (如 'page-login.php', 'templates/contact.php')
* @return int|false 頁面 ID 或 false
*/
function get_page_id_from_template(string $template) {
global $wpdb;
$page_id = $wpdb->get_var($wpdb->prepare("
SELECT pm.post_id
FROM {$wpdb->postmeta} pm
JOIN {$wpdb->posts} p ON p.ID = pm.post_id
WHERE pm.meta_key = '_wp_page_template'
AND pm.meta_value = %s
AND p.post_status = 'publish'
AND p.post_type = 'page'
LIMIT 1
", $template));
return $page_id ? (int) $page_id : false;
}
$login_page_id = get_page_id_from_template('page-login.php');
if ($login_page_id) {
echo '會員登入';
} else {
echo '會員登入'; // 回退預設
}
// Customizer 設定
$wp_customize->add_setting('contact_page_template', [
'default' => 'page-contact.php',
]);
$wp_customize->add_control('contact_page_template', [
'label' => '聯絡頁面模板',
'type' => 'select',
'choices' => [
'page-contact.php' => '聯絡頁面 v1',
'templates/contact2.php' => '聯絡頁面 v2',
],
]);
// 前台使用
$contact_template = get_theme_mod('contact_page_template', 'page-contact.php');
$contact_page_id = get_page_id_from_template($contact_template);
$contact_url = $contact_page_id ? get_permalink($contact_page_id) : home_url('/contact/');
// Polylang / WPML 相容:各語言建立對應模板頁面
$templates = [
'en' => 'page-contact-en.php',
'zh' => 'page-contact-zh.php',
'ja' => 'page-contact-ja.php',
];
$current_lang = pll_current_language() ?? 'en';
$page_id = get_page_id_from_template($templates[$current_lang] ?? $templates['en']);
| 方法 | 缺點 |
|---|---|
| 標題查詢 | 客戶可能修改標題、重複標題、多語言標題不同 |
| 別名查詢 | 客戶可能修改別名、別名衝突、需強制指定 |
| ID 硬編碼 | 環境遷移 (開發/測試/生產) ID 不一致 |
| 模板查詢 | 模板檔案由開發者控制、部署一致、語意明確 |
function get_page_ids_from_template(string $template): array {
global $wpdb;
return $wpdb->get_col($wpdb->prepare("
SELECT pm.post_id
FROM {$wpdb->postmeta} pm
JOIN {$wpdb->posts} p ON p.ID = pm.post_id
WHERE pm.meta_key = '_wp_page_template'
AND pm.meta_value = %s
AND p.post_status = 'publish'
AND p.post_type = 'page'
", $template));
}
// 使用:取得所有使用 'page-landing.php' 的頁面
$landing_pages = get_page_ids_from_template('page-landing.php');
foreach ($landing_pages as $page_id) {
// 處理...
}
WordPress 5.9+ 區塊主題使用 wp:template-{slug} 格式:
// 區塊主題模板查詢
$block_template_slug = 'contact-form'; // 區塊編輯器中建立的模板 slug
$page_id = get_page_id_from_template('wp:template-' . $block_template_slug);
function get_page_id_from_template_cached(string $template) {
$cache_key = 'page_id_from_template_' . md5($template);
$page_id = wp_cache_get($cache_key);
if ($page_id === false) {
$page_id = get_page_id_from_template($template);
wp_cache_set($cache_key, $page_id, 'template_queries', HOUR_IN_SECONDS);
}
return $page_id;
}
_wp_page_template 自訂欄位存儲模板關聯postmeta JOIN posts 過濾 post_status=publish + post_type=page掌握這個技巧,讓主題開發不再依賴脆弱的頁面 ID 或別名,實現真正可攜帶、可維護的模板綁定架構。