前言
在 WordPress 中,文章的 slug(網址別名)預設是根據標題自動產生,或由使用者手動設定。有時候為了簡化網址管理或避免重複 slug,會想將 slug 固定為文章的 ID。這段程式碼示範如何在文章發佈或排程時,自動將 slug 設為文章 ID,適合需要統一網址格式的開發者或網站管理者。
為什麼要用文章 ID 當 slug?
文章 ID 是 WordPress 中每篇文章的唯一識別碼,使用 ID 當 slug 可以避免重複 slug 的問題,也方便在程式中直接以 ID 取用文章,提升網址的穩定性與一致性。
程式碼解析
1. 使用 save_post Hook
程式碼利用 WordPress 的 save_post action,這個鉤子會在文章儲存時觸發,能即時修改文章資料。
add_action('save_post', function ($post_id, $post, $update) {
// 程式內容
}, 20, 3);
這裡設定優先權為 20,並且接受三個參數:文章 ID、文章物件、是否為更新。
2. 基本保護條件
避免對修訂版本(revision)或自動儲存(autosave)執行,減少不必要的處理。
if (wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) return;
if (!is_object($post)) return;
3. 限制只對文章類型生效
確保只對 post 文章類型操作,不影響其他自訂文章類型。
if ($post->post_type !== 'post') return;
4. 限制文章狀態
只對「已發佈(publish)」與「排程(future)」的文章改寫 slug,避免草稿或其他狀態執行。
$allowed_status = ['publish', 'future'];
if (!in_array($post->post_status, $allowed_status, true)) return;
5. 判斷是否已是目標 slug
如果 slug 已經是文章 ID,則不再重寫,避免重複操作。
$target_slug = (string) $post_id;
if ($post->post_name === $target_slug) return;
6. 防止無限迴圈
wp_update_post 會再次觸發 save_post,容易造成無限迴圈。使用靜態變數 $running 作為旗標,避免重複執行。
static $running = false;
if ($running) return;
$running = true;
7. 更新 slug
呼叫 wp_update_post 更新文章的 post_name 欄位為文章 ID。
wp_update_post([
'ID' => $post_id,
'post_name' => $target_slug,
]);
$running = false;
實務應用與延伸
- 適合網站需要簡潔、唯一的網址結構,或是避免標題相同導致 slug 重複的情況。
- 可擴充支援更多文章類型或狀態,只要調整條件判斷即可。
- 若需保留原本 slug,可改成在自訂欄位或其他欄位存 ID。
- 注意排程文章的 slug 會在排程時間前就設定完成。
常見問題與注意事項
- 無限迴圈問題是此類操作常見的陷阱,務必使用旗標避免。
- 使用文章 ID 當 slug 可能不利 SEO,需評估是否符合網站策略。
- 若網站有使用快取或重寫規則,更新 slug 後可能需要清除快取。
完整程式碼
<?php
/**
* Post 發佈時固定把 slug 設為文章 ID
* - 只針對 post(文章)
* - 避免無限迴圈
* - 若已是 ID slug 就不重寫
* - 支援 publish / future(排程)/ 更新時維持
*/
add_action('save_post', function ($post_id, $post, $update) {
// 1) 基本保護
if (wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) return;
if (!is_object($post)) return;
// 2) 只針對文章 post
if ($post->post_type !== 'post') return;
// 3) 只在這些狀態下固定(你也可以只留 publish)
$allowed_status = ['publish', 'future']; // future = 排程
if (!in_array($post->post_status, $allowed_status, true)) return;
// 4) 目標 slug = 文章 ID
$target_slug = (string) $post_id;
// 5) 已經是目標 slug 就不做事
if ($post->post_name === $target_slug) return;
// 6) 防止 save_post -> wp_update_post -> save_post 無限迴圈
static $running = false;
if ($running) return;
$running = true;
// 7) 更新 slug
wp_update_post([
'ID' => $post_id,
'post_name' => $target_slug,
]);
$running = false;
}, 20, 3);